STUDY AREA

ggplot() +
  geom_sf(data=srme) +
  geom_sf(data=wrnf, fill="darkgrey") +
  coord_sf(crs="EPSG:32613") +
  theme_bw(11)

Figure 1: Surface Reflectance / Spectral Response

head(ts)

Tidy the time-series data.

  1. Remove cloud-contaminated pixels,
  2. Pivot the table to gather bands,
  3. Generate mean/median/stdev of reflectance by image date,
  4. Calculate weekly summaries

Filter using the pixel cloud probability, scene classification, and remove erroneously high reflectance values:


tsp <- ts %>%
  filter(
    probability < 51, # less than 51% cloud probability
    ! SCL > 7 & SCL <= 10, # remove points labeled as cloud
    B8 < 5000 # remove points with very high near-infrared reflectance
  ) %>%
  # add the month as a column
  mutate(month = month(image_date, label=TRUE, abbr=TRUE))

tsp %>%
  group_by(image_date) %>%
  summarize(band = median(B8)) %>%
  ggplot(aes(x=image_date,y=band)) +
  geom_point(size=1.2) +
  geom_smooth(method="gam") +
  theme_bw(14)


ggplot(data=tsp, aes(x=B8, y=month)) +
  geom_boxplot() +
  coord_flip() +
  theme_bw()


rm(ts)

Now pivot the table longer:


tsp <- tsp %>%
  select(c(starts_with("B"),image_date,
           SLAVI,NDRE,NDMI,ChlRE,IRECI)) %>%
  group_by(image_date) %>%
  summarize_all(list(median)) %>%
  pivot_longer(
    cols = -image_date,
    names_to="band",
    values_to="refl"
  ) %>%
  # add a month and week label
  mutate(
    month = month(image_date, label=TRUE, abbr=TRUE),
    week = isoweek(image_date),
    week2 = cut.Date(image_date, breaks="2 week", labels=FALSE)
  )

head(tsp)
NA

Plot of median daily observations:

# Reorder band factors
tsp$band <- factor(tsp$band, 
                   levels = c("B2","B3","B4","B5","B6",
                              "B7","B8","B8A","B11","B12",
                              "ChlRE","IRECI","NDMI","NDRE","SLAVI"))

tsp %>%
  filter(str_detect(band,"B")) %>%
  ggplot(aes(x=image_date,y=refl,color=factor(band))) +
  geom_line(linewidth=0.4) +
  scale_color_viridis_d(option="turbo") +
  labs(x="Acquisition Date",y="Reflectance",color="S2 MSI Band") +
  theme_bw(14) +
  theme(axis.title.y = element_text(size=11,face="italic",
                                    margin = unit(c(0,0.4,0,0), "cm")),
        axis.title.x = element_text(size=11,face="italic",
                                    margin = unit(c(0.4,0,0,0), "cm")),
        axis.text = element_text(size=10),
        legend.text = element_text(size=10),
        legend.title = element_text(size=11))

Figure 3: Spectral Response of Aspen Forest Presence Data

Gather the seasonal composite start and end dates:

# Summer
(start_summer <- week(as.Date("2019-06-01")))
[1] 22
(end_summer <- week(as.Date("2019-09-14")))
[1] 37
# Autumn
(start_autumn <- week(as.Date("2019-09-16")))
[1] 37
(end_autumn <- week(as.Date("2019-11-30")))
[1] 48

Generate the weekly median reflectance.


# List for band colors

band_colors <- c(
  "B2"  = "#1E90FF",  # Blue: Dodger Blue
  "B3"  = "#00FF7F",  # Green: Spring Green
  "B4"  = "#FF0000",  # Red: Pure Red
  "B5"  = "#FFA07A",  # Red Edge: Light Salmon
  "B6"  = "#FF8C00",  # NIR: Dark Orange
  "B7"  = "#D2691E",  # NIR: Chocolate
  "B8"  = "#FFD700",  # NIR: Gold
  "B8A" = "#B8860B",  # NIR: Dark Goldenrod
  "B11" = "#008B8B",  # SWIR: Dark Cyan (dark shade of teal)
  "B12" = "#800080"   # SWIR: Purple
)


# Group by week, calculate the mean, plot

f3a <- tsp %>%
  filter(str_detect(band,"B")) %>%
  group_by(band,week) %>%
  summarize(refl = mean(refl)) %>%
  
  ggplot(aes(x=week,y=refl,color=factor(band))) +
  geom_line(linewidth=0.6) +
  scale_color_manual(values = band_colors) +
  labs(x="Acquisition Week",y="Reflectance",color=NULL) +
  theme_bw(11) +
  theme(axis.title.y = element_text(size=11,face="italic",
                                    margin = unit(c(0,0.4,0,0), "cm")),
        axis.title.x = element_text(size=11,face="italic",
                                    margin = unit(c(0.4,0,0,0), "cm")),
        axis.text = element_text(size=10),
        legend.text = element_text(size=8),
        legend.title = element_text(size=8),
        legend.position = c(0.2,0.85),
        legend.direction = "horizontal",
        legend.background = element_rect(fill="white", color="black"),
        plot.margin = unit(c(1.2,0.5,1.2,0.5), 'lines'),
        text = element_text(family = "Arial")) +
  annotate('rect', xmin=start_summer, xmax=end_autumn, ymin=0, ymax=4000, alpha=.3, fill='gray') +
  geom_vline(xintercept=start_autumn, linetype="dotted", lwd=0.8)
f3a

Figure 1B: Time-series charts of the spectral indices:


# All bands

tsp %>%
  group_by(band,week) %>%
  summarize(refl = mean(refl)) %>%
  ggplot(aes(x=week, y=refl, group=1)) +
  geom_line() +
  annotate('rect', xmin=22, xmax=48, ymin=0, ymax=Inf, alpha=.3, fill='gray') +
  geom_vline(xintercept=37, linetype="dotted") +
  facet_wrap(. ~ band, scales = "free") +
  theme_minimal() +
  theme(axis.title.y = element_text(size=8,face="italic",
                                    margin = unit(c(0,0.4,0,0), "cm")),
        axis.title.x = element_text(size=8,face="italic",
                                    margin = unit(c(0.4,0,0,0), "cm")),
        axis.text = element_text(size=7),
        strip.text.x = element_text(size = 8))


# Spectral indices

f3b <- tsp %>%
  filter(!str_detect(band,"B")) %>%
  group_by(band,week) %>%
  summarize(refl = mean(refl)) %>%
  ggplot(aes(x=week, y=refl, group=1)) +
  geom_line(linewidth=0.6) +
  labs(x="Acquisition Week",y="Reflectance") +
  annotate('rect', xmin=start_summer, xmax=end_autumn, ymin=0, ymax=Inf, alpha=.3, fill='gray') +
  geom_vline(xintercept=start_autumn, linetype="dotted", lwd=0.8) +
  facet_wrap(. ~ band, scales = "free") +
  theme_light(11) +
  theme(axis.title.y = element_text(size=11,face="italic",
                                    margin = unit(c(0,0.4,0,0), "cm")),
        axis.title.x = element_text(size=11,face="italic",
                                    margin = unit(c(0.4,0,0,0), "cm")),
        axis.text = element_text(size=10),
        strip.text.x = element_text(size = 11),
        plot.margin = unit(c(1.2,0.5,1.2,0.5), 'lines'),
        text = element_text(family = "Arial"))
f3b

Figure 3C: Boxplot of seasonal composites:


# Reorder band factors
tsp$band <- factor(tsp$band, 
                   levels = c("B2","B3","B4","B5","B6",
                              "B7","B8","B8A","B11","B12",
                              "ChlRE","IRECI","NDMI","NDRE","SLAVI"))

cols <- c(
  "Summer" = "#87CEEB", 
  "Autumn" = "#DAA520"
)

seasonal <- tsp %>%
  mutate(season = if_else(week>=22&week<=37,"Summer","na"),
         season = if_else(week>=37&week<=48,"Autumn",season)) %>%
  filter(season!="na")

seasonal$season <- factor(seasonal$season, levels = c("Summer","Autumn"))
  
f3c <- seasonal %>%
  filter(str_detect(band,"B")) %>%
  ggplot(aes(x=band,y=refl,fill=season)) +
  geom_boxplot(outlier.size = 0.5, outlier.color = "grey30") +
  scale_fill_manual(values = cols) +
  theme_bw(16) +
  labs(x="Sentinel-2 MSI Band",y="Reflectance") +
  theme(axis.title.y = element_text(size=11,face="italic",
                                    margin = unit(c(0,0.4,0,0), "cm")),
        axis.title.x = element_text(size=11,face="italic",
                                    margin = unit(c(0.4,0,0,0), "cm")),
        axis.text = element_text(size=10),
        legend.position = "none",
        plot.margin = unit(c(1.2,0.5,1.2,0.5), 'lines'),
        text = element_text(family = "Arial"))
f3c

Figure 1D: Seasonal differences in the spectral indices


f3d <- seasonal %>%
  filter(!str_detect(band,"B")) %>%
  ggplot(aes(y=refl)) +
  geom_boxplot(aes(fill=season)) +
  scale_fill_manual(values = cols) +
  facet_wrap(. ~ band, scales = "free") +
  theme_bw(14) +
  labs(fill="Season",y="Value") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x = element_blank(),
        axis.title.y = element_text(size=11,face="italic",
                                    margin = unit(c(0,0.4,0,0), "cm")),
        axis.title.x = element_text(size=11,face="italic",
                                    margin = unit(c(0.4,0,0,0), "cm")),
        axis.text = element_text(size=10),
        strip.text.x = element_text(size = 11),
        legend.position = c(0.85,0.2),
        legend.title = element_text(size=16),
        legend.text = element_text(size=15),
        plot.margin = unit(c(1.2,0.5,1.2,0.5), 'lines'),
        text = element_text(family = "Arial"))
f3d

Combine the plots:


# Arrange in a multi-panel plot

f3 <- ggarrange(f3a,f3b,f3c,f3d, nrow=2,ncol=2,widths=c(1, 0.75), labels = c("A", "B", "C", "D"))
Warning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font database
f3


# Save it out

ggsave(f3, file = "../../figures/Figure3_SpectralResponse.png",
       dpi = 300, bg="white") # adjust dpi accordingly

Version 2:


f3_ <- ggarrange(f3a,ggarrange(f3c,f3d,nrow=1,ncol=2),
                  ncol=1,widths=c(1, 0.75),
                  labels = c("A", "B", "C"))
Warning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font database
f3_


ggsave(f3_, file = "../../figures/Figure3_SpectralResponse_v2.png",
       dpi = 300, bg="white") # adjust dpi accordingly
Saving 14 x 8 in image

Clean up the time-series / spectral response data:

rm(f3,f3_,f3a,f3b,f3c,f3d,seasonal,tsp)
gc()
            used  (Mb) gc trigger   (Mb) limit (Mb)  max used   (Mb)
Ncells   3486807 186.3   10554481  563.7         NA  10554481  563.7
Vcells 114778541 875.7  299947880 2288.5      16384 299930662 2288.3

Figure 4: Model accuracy and feature importance plot

Best Performing Model:

Plot the AUC-PR and AUC-ROC.

glimpse(accmeas)
Rows: 1,000
Columns: 18
$ model       <dbl> 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 847, 84…
$ prSize      <dbl> 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 2901, 290…
$ bgSize      <dbl> 25590, 25590, 25590, 25590, 25590, 25590, 25590, 25590, 25590, 25590, 25590, 25590, 25590, 25590, 25590, 25590, 25590…
$ cutoff      <dbl> 0.00000000, 0.01010101, 0.02020202, 0.03030303, 0.04040404, 0.05050505, 0.06060606, 0.07070707, 0.08080808, 0.0909090…
$ tp          <dbl> 2901, 2864, 2845, 2829, 2813, 2803, 2788, 2781, 2768, 2753, 2739, 2729, 2722, 2712, 2707, 2694, 2688, 2680, 2676, 267…
$ tpr         <dbl> 1.0000000, 0.9872458, 0.9806963, 0.9751810, 0.9696656, 0.9662185, 0.9610479, 0.9586350, 0.9541537, 0.9489831, 0.94415…
$ fn          <dbl> 0, 37, 56, 72, 88, 98, 113, 120, 133, 148, 162, 172, 179, 189, 194, 207, 213, 221, 225, 231, 240, 244, 248, 254, 265,…
$ tn          <dbl> 0, 16107, 19280, 21100, 21893, 22463, 22844, 23177, 23424, 23628, 23829, 23975, 24089, 24194, 24305, 24399, 24499, 24…
$ tnr         <dbl> 0.0000000, 0.6294256, 0.7534193, 0.8245408, 0.8555295, 0.8778038, 0.8926925, 0.9057054, 0.9153576, 0.9233294, 0.93118…
$ fp          <dbl> 25590, 9483, 6310, 4490, 3697, 3127, 2746, 2413, 2166, 1962, 1761, 1615, 1501, 1396, 1285, 1191, 1091, 984, 902, 825,…
$ fpr         <dbl> 1.000000000, 0.370574443, 0.246580696, 0.175459164, 0.144470496, 0.122196170, 0.107307542, 0.094294646, 0.084642438, …
$ specificity <dbl> 0.0000000, 0.6294256, 0.7534193, 0.8245408, 0.8555295, 0.8778038, 0.8926925, 0.9057054, 0.9153576, 0.9233294, 0.93118…
$ precision   <dbl> 0.1018216, 0.2319592, 0.3107591, 0.3865282, 0.4321045, 0.4726813, 0.5037947, 0.5354255, 0.5610053, 0.5838812, 0.60866…
$ recall      <dbl> 1.0000000, 0.9872458, 0.9806963, 0.9751810, 0.9696656, 0.9662185, 0.9610479, 0.9586350, 0.9541537, 0.9489831, 0.94415…
$ f1          <dbl> 0.1848242, 0.3756558, 0.4719642, 0.5536204, 0.5978111, 0.6348092, 0.6610551, 0.6870908, 0.7065731, 0.7229517, 0.74017…
$ accuracy    <dbl> 0.1018216, 0.6658594, 0.7765610, 0.8398793, 0.8671510, 0.8868064, 0.8996525, 0.9110947, 0.9193079, 0.9259415, 0.93250…
$ gmean       <dbl> 0.0000000, 0.7882878, 0.8595787, 0.8967031, 0.9108115, 0.9209508, 0.9262398, 0.9317944, 0.9345544, 0.9360684, 0.93764…
$ mcc         <dbl> NA, 0.3763366, 0.4754020, 0.5535300, 0.5943626, 0.6287188, 0.6526159, 0.6770064, 0.6949038, 0.7098570, 0.7258652, 0.7…

Calculate the model averages using the optimum cutoff value:

# Without taking the average

print("~~~~~Total (not averageing)~~~~~")
[1] "~~~~~Total (not averageing)~~~~~"
(cutoffOptF1 = accmeas[which.max(accmeas$f1),]$cutoff)
[1] 0.6565657
(precisionOptF1 = accmeas[which.max(accmeas$f1),]$precision)
[1] 0.9575117
(recallOptF1 = accmeas[which.max(accmeas$f1),]$recall)
[1] 0.9131408
(fprOpt = accmeas[which.max(accmeas$f1),]$fpr)
[1] 0.01006562
(tprOpt = accmeas[which.max(accmeas$f1),]$tpr)
[1] 0.9131408
# With the aggregation/averaging across models and threshold values

# Calculate the averages for each cutoff value across model runs

accmeas.mn <- accmeas %>%
  mutate(cutoff = as.character(cutoff)) %>%
  group_by(cutoff) %>%
  summarise(
    prMn = mean(prSize,na.rm=T), # size of presence data (mean)
    prSd = sd(prSize,na.rm=T), # size of presence data (sd)
    bgMn = mean(bgSize,na.rm=T), # size of background data (mean)
    bgSd = sd(bgSize,na.rm=T), # size of background data (sd)
    fprMn = mean(fpr,na.rm=T), # False Positive Rate (mean)
    fprSd = sd(fpr,na.rm=T),
    tprMn = mean(tpr,na.rm=T), # True Positive Rate (mean)
    tprSd = sd(tpr,na.rm=T),
    precision = mean(precision,na.rm=T), # precision (mean)
    precisionSd = sd(precision,na.rm=T), 
    recall = mean(recall,na.rm=T), # recall (mean)
    recallSd = sd(recall,na.rm=T),
    f1 = mean(f1,na.rm=T), # F1 score (mean)
    f1Sd = sd(f1,na.rm=T),
    gmean = mean(gmean,na.rm=T), # Geometric Mean (mean)
    gmeanSd = sd(gmean,na.rm=T),
    mcc = mean(mcc,na.rm=T), # Matthew's Correlation Coefficient (mean)
    mccSd = sd(mcc,na.rm=T),
    accuracy = mean(accuracy,na.rm=T), # Overall accuracy (mean)
    accuracySd = sd(accuracy,na.rm=T)
  ) %>%
  ungroup() %>%
  mutate(cutoff = round(as.double(cutoff),3))

# Calculate optimum threshold based on F1 statistic

cutoffOptMn = accmeas.mn[which.max(accmeas.mn$f1),]$cutoff
precisionOptF1Mn = accmeas.mn[which.max(accmeas.mn$f1),]$precision
recallOptF1Mn = accmeas.mn[which.max(accmeas.mn$f1),]$recall
fprOptMn = accmeas.mn[which.max(accmeas.mn$f1),]$fprMn
tprOptMn = accmeas.mn[which.max(accmeas.mn$f1),]$tprMn
max_f1 <- max(accmeas.mn$f1, na.rm = TRUE)
# F1 based
print("F1-based accuracy metrics:")
[1] "F1-based accuracy metrics:"
paste0("F1 Score: ",(f1Opt = accmeas.mn[which.max(accmeas.mn$f1),]$f1))
[1] "F1 Score: 0.910339477355629"
paste0("Overall Accuracy: ",(oaOpt = accmeas.mn[which.max(accmeas.mn$f1),]$accuracy))
[1] "Overall Accuracy: 0.972760973096824"
paste0("Precision: ",(precOpt = accmeas.mn[which.max(accmeas.mn$f1),]$precision))
[1] "Precision: 0.923031953935543"
paste0("Recall: ",(recOpt = accmeas.mn[which.max(accmeas.mn$f1),]$recall))
[1] "Recall: 0.899585913024552"
paste0("Cutoff: ",(threshOpt = accmeas.mn[which.max(accmeas.mn$f1),]$cutoff))
[1] "Cutoff: 0.424"
# Mathews Correlation Coefficient
print("---------------------------")
[1] "---------------------------"
print("MCC-based accuracy metrics:")
[1] "MCC-based accuracy metrics:"
paste0("MCC: ",(mccOpt = accmeas.mn[which.max(accmeas.mn$mcc),]$mcc))
[1] "MCC: 0.894765492997981"
paste0("Overall Accuracy: ",(oaOptmcc = accmeas.mn[which.max(accmeas.mn$mcc),]$accuracy))
[1] "Overall Accuracy: 0.97280285805149"
paste0("Precision: ",(precOptmcc = accmeas.mn[which.max(accmeas.mn$mcc),]$precision))
[1] "Precision: 0.925644674464425"
paste0("Recall: ",(recOptmcc = accmeas.mn[which.max(accmeas.mn$mcc),]$recall))
[1] "Recall: 0.89698605744059"
paste0("Cutoff: ",(threshOptmcc = accmeas.mn[which.max(accmeas.mn$mcc),]$cutoff))
[1] "Cutoff: 0.434"

Plot the model accuracy results for the optimum threshold.


# Get the best F1 score for each model run
accmeas.best <- accmeas %>% 
  group_by(factor(model)) %>% top_n(1,f1) %>%
  ungroup() %>%
  mutate(model_iter = row_number())

print(paste0("Cutoff: Mean = ",round(mean(accmeas.best$cutoff),3),"; Standard Deviation: ",round(sd(accmeas.best$cutoff),3)))
[1] "Cutoff: Mean = 0.441; Standard Deviation: 0.118"
print(paste0("F1 Score: Mean = ",round(mean(accmeas.best$f1),3),"; Standard Deviation: ",round(sd(accmeas.best$f1),3)))
[1] "F1 Score: Mean = 0.915; Standard Deviation: 0.016"

Figure 4A: Model Accuracy (F1 and OA)


cols <- c("F1 Score"="#1f78b4","Overall Accuracy"="gray75")

f4a <- ggplot(data=accmeas.best) +
  geom_hline(yintercept=0.972760973096824,linetype="dashed",color="gray85") +
  geom_hline(yintercept=0.910339477355629,linetype="dashed",color="#1f78b4") +
  geom_line(aes(x=factor(model_iter),y=accuracy,group=1),color="gray65") +
  geom_line(aes(x=factor(model_iter),y=f1,group=1),color="#1f78b4") +
  geom_point(aes(x=factor(model_iter),y=f1,size=f1), color="#1f78b4") +
  geom_point(aes(x=factor(model_iter),y=accuracy,size=accuracy), color="gray65") +
  scale_size(range = c(3,6)) +
  coord_cartesian(ylim = c(0.85, 1)) +
  labs(x="Model Iteration", y="Score", tag="A") +
  annotate("text", x = 3, y = 0.99, label = paste("Average Overall Accuracy: ", round(oaOpt, 2))) +
  annotate("text", x = 2.6, y = 0.88, label = paste("Average F1 Score: ", round(f1Opt, 2))) +
  theme_bw() +
  guides(size="none") +
  theme(
        plot.margin = unit(c(0.2,0.2,0.2,0.2), 'lines'),
        axis.title.y = element_text(size=11,face="italic",
                                    margin = unit(c(0,0.4,0,0), "cm")),
        axis.title.x = element_text(size=11,face="italic",
                                    margin = unit(c(0.4,0,0,0), "cm")),
        axis.text = element_text(size=10),
        strip.text.x = element_text(size = 11),
        text = element_text(family = "Arial"))
f4a

ggsave(f4a, file = "../../figures/Figure4A_Best_Model_Acc_F1.png",
       dpi = 300, bg="white") # adjust dpi accordingly

Figure 4B: Sensitivity Analysis


# Labels for each model subset

labels_ = c(
  "winter_sar" = "M1", 
  "summer_sar" = "M2",
  "summer_winter_sar_text" = "M3",
  "summer_winter_sar" = "M4",
  "autumn_spectral" = "M5",
  "summer_spectral" = "M6",
  "summer_spectral_ind" = "M7",
  "spectral_sar_ind" = "M8",
  "summer_autumn_spectral" = "M9",
  "spectral_sar" = "M10",
  "final" = "Final Model"
)

# Add in the final model to the sensitivity analysis

add <- accmeas.best %>%
  ungroup() %>%
  select(model,f1) %>%
  mutate(subset = "final") %>%
  rename(f1Max = f1)
glimpse(add)
Rows: 10
Columns: 3
$ model  <dbl> 847, 991, 343, 197, 783, 9, 283, 777, 588, 708
$ f1Max  <dbl> 0.8906140, 0.9021872, 0.9219364, 0.9084126, 0.9225152, 0.9348000, 0.8911798, 0.9283032, 0.9264555, 0.9200240
$ subset <chr> "final", "final", "final", "final", "final", "final", "final", "final", "final", "final"
accmeas.s <- accmeas.s %>%
  bind_rows(add)
rm(add)

print(unique(accmeas.s$subset))
 [1] "autumn_spectral"        "spectral_sar_ind"       "spectral_sar"           "summer_autumn_spectral" "summer_sar"            
 [6] "summer_spectral_ind"    "summer_spectral"        "summer_winter_sar_text" "summer_winter_sar"      "winter_sar"            
[11] "final"                 
# Generate the box plots of F1 score

f4b <- ggplot(data=accmeas.s, aes(x=reorder(subset,f1Max),y=f1Max)) +
  geom_boxplot() +
  scale_x_discrete(labels=labels_) +
  labs(x="Input Features",y="Maximum F1 Score", tag="B") +
  theme_bw(11) +
  theme(
        plot.margin = unit(c(0.2,0.2,0.2,0.2), 'lines'),
        axis.title.y = element_text(size=11,face="italic",
                                    margin = unit(c(0,0.4,0,0), "cm")),
        axis.title.x = element_text(size=11,face="italic",
                                    margin = unit(c(0.4,0,0,0), "cm")),
        axis.text = element_text(size=10),
        strip.text.x = element_text(size = 11),
        axis.text.x = element_text(angle = 45, hjust=1),
        text = element_text(family = "Arial"))
f4b

# Save out

ggsave(f4b, file = "../../figures/Figure4B_Model_Sensitivity.png",
       dpi = 300, bg="white") # adjust dpi accordingly
Saving 7.29 x 4.51 in image

Combine the two figures for Figure 4AB:


f4 <- ggarrange(f4a,f4b,nrow=2)
Warning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font database
f4


ggsave(f4, file = "../../figures/Figure4AB_Model_Accuracy_Sensitivity.png",
       width=7.5, height=7.5, dpi = 300, bg="white") # adjust dpi accordingly

Figure 6: Feature importance from the best model

glimpse(ftr_imp)
Rows: 10
Columns: 40
$ `system:index`     <dbl> 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
$ B11_autumn         <dbl> 21.63001, 24.71046, 26.31618, 24.16826, 28.99346, 19.68919, 22.29900, 25.98756, 23.72236, 18.54693
$ B11_summer         <dbl> 32.61777, 88.15568, 60.08632, 53.96426, 73.95518, 72.80209, 52.43871, 80.31342, 50.76397, 69.10347
$ B12_autumn         <dbl> 8.754374, 7.762443, 8.792581, 9.551003, 12.785215, 5.251996, 8.192395, 8.501508, 10.572703, 6.456701
$ B12_summer         <dbl> 31.83856, 52.96160, 38.76007, 38.55945, 50.41913, 48.07633, 39.51833, 42.83267, 29.81382, 40.09193
$ B2_autumn          <dbl> 11.01432, 37.32868, 23.77948, 17.83080, 33.41181, 19.94616, 16.71003, 24.59457, 19.34141, 19.19359
$ B2_summer          <dbl> 1.544011, 4.428377, 2.925933, 3.246131, 3.434643, 3.485534, 2.789854, 3.784211, 4.843380, 3.900492
$ B3_autumn          <dbl> 32.90573, 92.48967, 84.06609, 65.37862, 69.08507, 72.15569, 53.37248, 90.80987, 69.53004, 63.90807
$ B3_summer          <dbl> 14.483419, 16.379753, 13.108126, 9.564537, 10.055796, 12.936688, 10.481147, 14.919178, 18.070886, 15.289636
$ B4_autumn          <dbl> 15.46758, 31.21614, 26.98158, 17.52866, 23.64321, 24.35671, 21.20621, 25.54006, 25.99864, 18.95956
$ B4_summer          <dbl> 25.03937, 34.02723, 31.25796, 19.47697, 20.00762, 34.28381, 25.24520, 31.07726, 32.81473, 34.92248
$ B5_autumn          <dbl> 7.159686, 22.725072, 20.973219, 13.242495, 16.899435, 16.774081, 12.558062, 21.655292, 24.347260, 13.619232
$ B5_summer          <dbl> 13.05487, 23.06441, 21.29735, 15.21438, 10.23691, 25.19220, 15.07107, 26.41282, 21.99278, 16.44929
$ B6_autumn          <dbl> 3.143607, 12.979872, 16.181342, 9.231907, 9.704828, 13.313262, 6.281355, 12.702162, 13.859885, 14.459542
$ B6_summer          <dbl> 9.630015, 14.326921, 16.189771, 8.770566, 9.178170, 9.114085, 7.018957, 18.397494, 13.348548, 14.043514
$ B8_autumn          <dbl> 1.751561, 8.387896, 7.606446, 5.830232, 4.035430, 5.854015, 2.170036, 5.069091, 8.652400, 3.776282
$ ChlRE_autumn       <dbl> 12.98923, 21.18098, 22.66903, 15.78830, 17.69833, 17.75489, 11.87762, 20.72763, 23.82522, 20.97342
$ ChlRE_summer       <dbl> 82.17996, 101.93907, 105.73092, 103.51654, 102.97492, 105.56823, 98.30599, 101.28398, 96.24895, 110.02008
$ IRECI_autumn       <dbl> 1.6542028, 3.2196484, 2.3650415, 0.7022645, 1.6526279, 1.0071467, 1.0040322, 3.2029031, 2.5123898, 1.0397889
$ IRECI_summer       <dbl> 14.16647, 21.94451, 24.55819, 21.98607, 22.44355, 20.32083, 17.31854, 21.83391, 26.52660, 18.86483
$ NDMI_autumn        <dbl> 5.284292, 6.409813, 8.680610, 9.148087, 8.801485, 5.467554, 4.800973, 7.988817, 12.338028, 7.960924
$ NDMI_summer        <dbl> 26.60976, 25.41538, 25.41944, 38.26568, 42.14366, 35.12636, 32.01464, 26.38395, 17.69483, 31.65604
$ NDRE_autumn        <dbl> 7.091025, 13.491095, 9.905432, 5.922877, 8.751692, 8.572938, 7.119315, 12.678073, 9.988859, 9.150386
$ NDRE_summer        <dbl> 74.55249, 85.95997, 92.60474, 89.07581, 94.71430, 93.68764, 83.93495, 89.60477, 93.61925, 87.67304
$ SLAVI_autumn       <dbl> 0.7581965, 2.1182702, 1.5958263, 0.6020280, 1.7417527, 1.2952044, 1.5542184, 1.7272081, 0.9213949, 0.9790948
$ SLAVI_summer       <dbl> 44.26112, 54.30483, 56.35111, 52.61809, 52.49489, 51.57909, 44.03826, 52.53019, 45.75043, 49.18132
$ VH_summer          <dbl> 148.4425, 178.3843, 171.8808, 146.9129, 168.2566, 144.1681, 165.2832, 160.8539, 177.6198, 149.5917
$ VH_summer_contrast <dbl> 7.431997, 3.403814, 2.495050, 2.771170, 5.822993, 4.309862, 2.731022, 3.218622, 5.673280, 3.403127
$ VH_summer_ent      <dbl> 8.109652, 4.510600, 6.983570, 3.173383, 5.992742, 4.668601, 5.488646, 7.298885, 6.797872, 3.575809
$ VH_winter          <dbl> 32.73627, 39.91918, 38.24390, 32.68237, 43.17811, 36.18398, 42.17934, 39.50431, 47.89564, 42.82106
$ VH_winter_contrast <dbl> 7.067432, 4.903738, 5.184350, 3.717707, 5.418322, 7.437393, 4.987159, 4.303950, 5.951391, 2.591191
$ VH_winter_ent      <dbl> 3.904413, 3.505374, 3.297951, 4.277354, 3.182406, 5.360329, 3.818240, 3.681942, 7.229823, 2.231365
$ VV_summer          <dbl> 82.46562, 87.00165, 80.80692, 71.20855, 76.14901, 80.24709, 86.91908, 82.11989, 76.76129, 69.76924
$ VV_summer_contrast <dbl> 4.015073, 4.000985, 6.338935, 4.541748, 5.589750, 6.125613, 4.943460, 3.774304, 5.980394, 5.599165
$ VV_summer_ent      <dbl> 3.709408, 3.447794, 6.666000, 3.654588, 5.257164, 9.238666, 4.542707, 4.675496, 7.836229, 6.438189
$ VV_winter          <dbl> 19.56131, 22.65798, 22.86519, 19.75495, 19.27481, 25.02942, 24.92029, 20.98694, 24.95799, 22.82763
$ VV_winter_contrast <dbl> 0.9623009, 2.4274726, 3.7450767, 1.6043663, 2.6151410, 1.8423834, 1.8399639, 1.1207479, 4.6077801, 1.4807937
$ VV_winter_ent      <dbl> 0.7249480, 1.5235996, 1.5404339, 0.2233372, 1.7780329, 0.8068386, 1.2452230, 0.5372814, 2.7943568, 1.9884459
$ seed               <dbl> 923, 940, 534, 301, 823, 754, 610, 358, 201, 811
$ .geo               <chr> "{\"type\":\"MultiPoint\",\"coordinates\":[]}", "{\"type\":\"MultiPoint\",\"coordinates\":[]}", "{\"type\":\"M…

# # Tidy the data frame
# df.imp <- ftr_imp %>% 
#   select(-c(.geo,`system:index`)) %>%
#   rename(model = seed) %>%
#   mutate(model = as.factor(model)) %>%
#   # Summarize across to grab the relative importance
#   rowwise() %>%
#   mutate(total = sum(c_across(B11_autumn:VV_winter_ent))) %>%
#   ungroup() %>%
#   mutate(across(B11_autumn:VV_winter_ent, ~ . * 100 / total)) %>%
#   select(-total)
# glimpse(df.imp)

# Tidy the data frame
df.imp <- ftr_imp %>% 
  select(-c(.geo,`system:index`)) %>%
  rename(model = seed) %>%
  mutate(model = as.factor(model)) %>%
  # Summarize across to grab the relative importance
  group_by(model) %>%
  mutate(total = sum(across(B11_autumn:VV_winter_ent))) %>%
  mutate(across(B11_autumn:VV_winter_ent, ~ . / total)) %>%
  ungroup() %>%
  select(-total)

# Pivot longer
df.imp.p <- df.imp %>%
  pivot_longer(cols = -model) %>%
  rename(importance = value,
         band = name) %>%
  mutate(season = if_else(str_detect(band,"_autumn"), "Autumn Spectral", "Summer Spectral"),
         season = if_else(str_detect(band,"VV_winter"), "Winter SAR", season),
         season = if_else(str_detect(band,"VH_winter"), "Winter SAR", season),
         season = if_else(str_detect(band,"VV_summer"), "Summer SAR", season),
         season = if_else(str_detect(band,"VH_summer"), "Summer SAR", season))
glimpse(df.imp.p)
Rows: 370
Columns: 4
$ model      <fct> 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923, 923…
$ band       <chr> "B11_autumn", "B11_summer", "B12_autumn", "B12_summer", "B2_autumn", "B2_summer", "B3_autumn", "B3_summer", "B4_autumn…
$ importance <dbl> 0.0264195433, 0.0398403235, 0.0106928546, 0.0388885671, 0.0134532179, 0.0018859015, 0.0401920479, 0.0176904816, 0.0188…
$ season     <chr> "Autumn Spectral", "Summer Spectral", "Autumn Spectral", "Summer Spectral", "Autumn Spectral", "Summer Spectral", "Aut…

# Grab the top 20 over all model runs

top <- df.imp.p %>%
  group_by(band) %>%
  summarize(median = median(importance)) %>%
  ungroup()

top <- head(arrange(top,desc(median)), n = 20)

# Color palette

cols <- c(
  "Summer Spectral" = "#87CEEB", 
  "Autumn Spectral" = "#DAA520",
  "Winter SAR" = "gray29",
  "Summer SAR" = "gray89"
)

# Boxplot

# %>% filter(band %in% top$band)
f6 <- ggplot(data=df.imp.p %>% filter(band %in% top$band), 
              aes(x=reorder(band,importance), fill=season)) +
  geom_boxplot(aes(y=importance), position = position_dodge(0.5)) +
  scale_fill_manual(values = cols, 
                    labels = c("Autumn Spectral","Summer SAR","Summer Spectral","Winter SAR")) +
  coord_flip() +
  theme_bw(11) +
  theme(axis.text.x = element_text(size=11),
        axis.text.y = element_text(angle = 0, vjust=0, size=11),
        axis.title = element_text(size=11,face="italic"),
        legend.position = "bottom",
        legend.justification = c(1.2,0.5), # Left-aligns the legends
        legend.text = element_text(size=11),
        text = element_text(family = "Arial"),
        plot.margin=unit(c(0.5,0.5,0.5,0.5),"cm")) +
  labs(x="Feature", y="Importance", fill="Season: ")
f6

ggsave(f6, file = "../../figures/Figure6_FeatureImportance.png",
       dpi=300, bg="white") # adjust dpi accordingly

Clean up!

rm(list = ls.str(mode = 'numeric'))
rm(accmeas,accmeas.best,accmeas.mn,accmeas.s,df.imp,
   df.imp.p,f4,f4a,f4b,f6,ftr_imp,top)
gc()
            used  (Mb) gc trigger   (Mb) limit (Mb)  max used   (Mb)
Ncells   3476244 185.7   10554481  563.7         NA  10554481  563.7
Vcells 114720624 875.3  299947880 2288.5      16384 299930662 2288.3

Figures 7, 8 - Case Study: Landscape Patch Dynamics

Figure 7: Spatial Agreement


brewer.pal(n=5,"Set1")
[1] "#E41A1C" "#377EB8" "#4DAF4A" "#984EA3" "#FF7F00"
cols <- c("#4DAF4A", "#984EA3", "#FF7F00")

glimpse(ref.global)
Rows: 30
Columns: 9
$ blocksize <dbl> 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9
$ tp        <dbl> 9624656, 2302057, 1183801, 756552, 537725, 9054690, 2366565, 1233728, 792221, 563383, 11730465, 2448883, 1170711, 71896…
$ fp        <dbl> 7010703, 1121162, 483983, 278722, 184080, 7580669, 1056654, 434056, 243053, 158422, 4904894, 974336, 497073, 316306, 22…
$ fn        <dbl> 5626219, 1153016, 524296, 301318, 194575, 7147207, 1796140, 831246, 471351, 298504, 15402301, 1788412, 602423, 289372, …
$ prec      <dbl> 0.5785662, 0.6724831, 0.7098047, 0.7307747, 0.7449727, 0.5443039, 0.6913274, 0.7397409, 0.7652283, 0.7805197, 0.7051525…
$ rec       <dbl> 0.6310888, 0.6662832, 0.6930526, 0.7151654, 0.7342961, 0.5588660, 0.5685161, 0.5974545, 0.6269694, 0.6536623, 0.4323358…
$ source    <chr> "LFEVT", "LFEVT", "LFEVT", "LFEVT", "LFEVT", "TreeMap", "TreeMap", "TreeMap", "TreeMap", "TreeMap", "ITSP", "ITSP", "IT…
$ region    <chr> "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME",…
$ f1        <dbl> 0.6036872, 0.6693688, 0.7013286, 0.7228858, 0.7395958, 0.5514888, 0.6239359, 0.6610276, 0.6892336, 0.7114805, 0.5360278…
# Get an average f1 score table
f1mn <- ref.global %>%
  group_by

# Add a statistics column for legend (could do this for F1 too ...)
ref.global.m <- reshape2::melt(
  ref.global, id.vars = c("blocksize", "source", "region"), 
  measure.vars = c("prec", "rec"), variable.name = "statistic"
)

glimpse(ref.global.m)
Rows: 60
Columns: 5
$ blocksize <dbl> 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9, 1, 3, 5, 7, 9,…
$ source    <chr> "LFEVT", "LFEVT", "LFEVT", "LFEVT", "LFEVT", "TreeMap", "TreeMap", "TreeMap", "TreeMap", "TreeMap", "ITSP", "ITSP", "IT…
$ region    <chr> "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME", "SRME",…
$ statistic <fct> prec, prec, prec, prec, prec, prec, prec, prec, prec, prec, prec, prec, prec, prec, prec, prec, prec, prec, prec, prec,…
$ value     <dbl> 0.5785662, 0.6724831, 0.7098047, 0.7307747, 0.7449727, 0.5443039, 0.6913274, 0.7397409, 0.7652283, 0.7805197, 0.7051525…
f7a <- ggplot(data=ref.global.m) +
  geom_line(aes(x=blocksize,y=value,color=factor(source), linetype=statistic), linewidth=0.6) +
  geom_point(data=ref.global, aes(x=blocksize, y=f1, color=source)) +
  scale_x_continuous(breaks=c(1,3,5,7,9)) +
  scale_linetype_manual(values = c("prec" = "dotted", "rec" = "solid"), name="Statistic: ",
                        labels=c("Precision","Recall")) +
  facet_wrap(~region, scales = "fixed") +
  scale_color_manual(values=cols, labels=c("LANDFIRE EVT","USFS TreeMap","USFS ITSP"), name="Source: ") +
  theme_light(14) +
  ylim(0,1) +
  theme(legend.position = "top",
        legend.box = "vertical",
        legend.justification = c(0.5,0.5), # Left-aligns the legends
        legend.spacing.y = unit(-10, "pt"), # Adjusts the gap between the legends
        legend.text = ggtext::element_markdown(halign = 0), # This aligns each individual legend's text to the left
        axis.title = element_text(size=12,face="italic"),
        text = element_text(family = "Arial")) +
  labs(x="Blocksize (pixels)",y="Value")
  
f7a

ggsave(f7a, file = "../../figures/Figure7_Global_PrecRec_Agreement.png", dpi=300)
Saving 7.29 x 4.51 in image

Focal accuracy:


# ref.focal$refbudens <- log(1 + ref.focal$tp + ref.focal$fn)
# 
# ggplot(ref.focal %>% filter(region=="SRME"), aes(x = prec, y = rec, color = refbudens)) +
#    geom_point(size = 2, alpha = 0.9) +
#    scale_color_viridis_c() +
#    facet_grid(rows = vars(geog_scale), cols = vars(blocksize), scales = "fixed") +
#    theme_light() +
#    labs(
#       title = 'Spatially explicit accuracy: Precision (x) vs. Recall (y)',
#       subtitle = 'for multiple analytical units and spatial support levels',
#       color = 'refbudens',
#       x = 'Precision',
#       y = 'Recall'
#    ) +
#    coord_cartesian(xlim = c(0, 1), ylim = c(0, 1)) +
#    theme(legend.position = "bottom")

Join the two plots:

# f7 <- ggarrange(global_precrec,focal.prec,focal.rec,nrow=1,labels=c("A","B","C"))
# f7
# ggsave(f7, file="../../figures/Figure7_Global_Focal_Agreement.png", dpi=300)

Clean up!

rm(ref.global,ref.global.m,f7a,f7b,f7,ref.focal)
Warning: object 'f7b' not foundWarning: object 'f7' not found
gc()
           used  (Mb) gc trigger   (Mb) limit (Mb)  max used   (Mb)
Ncells  3500531 187.0   10554481  563.7         NA  10554481  563.7
Vcells 42536015 324.6  239958304 1830.8      16384 299930662 2288.3

Figure 8: Landscape Patch Dynamics

unique(factor(patch_metrics$source))
[1] LFEVT    ITSP     TreeMap  Aspen10m Aspen30m
Levels: Aspen10m Aspen30m ITSP LFEVT TreeMap
summary(patch_metrics)
       X               index              area             perimeter        perimeter_area_ratio  shape_index         region         
 Min.   :      0   Min.   :      0   Min.   :     0.01   Min.   :      40   Min.   :  72.95      Min.   :  1.000   Length:5145088    
 1st Qu.: 180181   1st Qu.: 180181   1st Qu.:     0.05   1st Qu.:     100   1st Qu.:1000.00      1st Qu.:  1.000   Class :character  
 Median : 489868   Median : 489868   Median :     0.09   Median :     120   Median :1333.33      Median :  1.000   Mode  :character  
 Mean   : 594419   Mean   : 594419   Mean   :     1.72   Mean   :     561   Mean   :1728.38      Mean   :  1.249                     
 3rd Qu.: 920401   3rd Qu.: 920401   3rd Qu.:     0.27   3rd Qu.:     280   3rd Qu.:2333.33      3rd Qu.:  1.333                     
 Max.   :1822292   Max.   :1822292   Max.   :145661.31   Max.   :16467240   Max.   :4000.00      Max.   :119.887                     
    source         
 Length:5145088    
 Class :character  
 Mode  :character  
                   
                   
                   

Calculate some grouped statistics (to compare with the class metrics results)


# Also create a grouped summary
(patch.summary <- patch_metrics %>%
  group_by(source,region) %>%
  summarize(area_md = median(area), # convert to hectares
            area_mn = mean(area),
            area_sum = sum(area),
            perim_md = median(perimeter),
            perim_mn = mean(perimeter),
            par_md = median(perimeter_area_ratio),
            par_mn = mean(perimeter_area_ratio),
            si_md = median(shape_index),
            si_mn = mean(shape_index)) %>%
  ungroup())

(patch.long <- patch.summary %>%
  pivot_longer(cols = c(contains("_")),
               names_to = "metric",
               values_to = "value"))

patch.long$source <- factor(patch.long$source,levels=c('Aspen10m', 'Aspen30m', 'LFEVT', 'TreeMap', 'ITSP'))

(ggplot(data = patch.long, aes(x=source, y=value, fill=region)) +
    geom_bar(stat="identity", position="dodge", width=0.7) +
    facet_wrap(~metric, scales="free") + 
    theme_minimal(14) +
    theme(axis.text.x = element_text(angle = 45, hjust = 1),
    text = element_text(family = "Arial")))


(f8s <- ggplot(data = patch.long, aes(x=source, y=value, fill=region)) +
    geom_bar(stat="identity", position="dodge", width=0.7) + 
    theme_minimal(14) +
    theme(axis.text.x = element_text(angle = 45, hjust = 1),
    text = element_text(family = "Arial")))

Grab some statistics on the patch size:

(a <- patch.long %>% filter(metric=="area_mn",source=="Aspen10m"))
(b <- patch.long %>% filter(metric=="area_mn",source=="LFEVT"))

(c <- patch.long %>% filter(metric=="area_md",source=="Aspen10m"))
(d <- patch.long %>% filter(metric=="area_md",source=="LFEVT"))

print("Mean and median patch sizes: ")
[1] "Mean and median patch sizes: "
paste0("Aspen10m mean: ",a$value)
[1] "Aspen10m mean: 0.520332932190088" "Aspen10m mean: 0.728109887310855"
paste0("LFEVT mean: ",b$value)
[1] "LFEVT mean: 1.77358052624186" "LFEVT mean: 3.39937585008331"
paste0("Aspen10m median: ",c$value)
[1] "Aspen10m median: 0.03" "Aspen10m median: 0.02"
paste0("LFEVT mean: ",d$value)
[1] "LFEVT mean: 0.18" "LFEVT mean: 0.18"
print("Difference in mean area: ")
[1] "Difference in mean area: "
((b$value-a$value)/b$value)*100
[1] 70.66201 78.58107
print("Difference in median area: ")
[1] "Difference in median area: "
((d$value-c$value)/d$value)*100
[1] 83.33333 88.88889
print("Mean Perimeter area ratio: ")
[1] "Mean Perimeter area ratio: "
(a <- patch.long %>% filter(metric=="par_mn",source=="Aspen10m"))
(b <- patch.long %>% filter(metric=="par_mn",source=="LFEVT"))

print("Difference in PAR: ")
[1] "Difference in PAR: "
((b$value-a$value)/b$value)*100
[1] -154.6593 -169.6188
rm(a,b,c,d)

Boxplot as facet wrap for patch metrics:


brewer.pal(n=5,"Set1")
[1] "#E41A1C" "#377EB8" "#4DAF4A" "#984EA3" "#FF7F00"
cols <- c("#005a32","#a1d99b")

(df <- patch_metrics %>%
  # mutate(area_ha = area*100) %>%
  select(-c(X,index,shape_index)) %>%
  pivot_longer(contains(c("area","perimeter_area_ratio"))) %>%
  arrange(source, desc(value)) %>%
  mutate(name = as.character(name),
         name = recode(name,
                       "area" = "Patch Size (ha)",
                       "perimeter_area_ratio" = "Perimeter/Area Ratio")))

df$source <- factor(df$source,
                    levels=c('Aspen10m', 'Aspen30m', 'LFEVT', 'TreeMap', 'ITSP'))
 
(f8a <- ggplot(data=df, aes(y = value, x = factor(source), fill = factor(region))) +
  geom_boxplot(outlier.size = 0.2) +
  scale_y_continuous(trans="log10",labels=label_number_si(accuracy = 1)) +
  scale_fill_manual(values=cols) +
  facet_wrap(~name, scales = "free_y", nrow=1) +
  labs(x="\nData Source",y="Value",title="Patch Metrics", fill="Region: ") +
  theme_light(12) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1, size=11),
        axis.text.y = element_text(angle = 0, vjust=0.1, size=11),
        axis.title.y = element_text(size=12, face="italic", vjust=1),
        axis.title.x = element_text(size=12, face="italic", vjust=-1),
        plot.margin = unit(c(0.5,0.5,0.5,0.5),"cm"),
        legend.position="top",
        legend.spacing.x = unit(0.5,"cm"),
        text = element_text(family = "Arial")))
Warning: `label_number_si()` was deprecated in scales 1.2.0.
Please use the `scale_cut` argument of `label_number()` instead.

ggsave(f8a, file = "../../figures/Figure8A_patch_metrics.png", dpi = 300) # adjust dpi accordingly
Saving 10 x 5 in image

Plot class metrics as facet wrap:


# Calculate area in square meters
srme_area_km2 <- st_area(srme) / 1e6
wrnf_area_km2 <- st_area(wrnf) / 1e6

(df <- class_metrics %>%
  mutate(total_area = total_area*0.01,
         prop_area = if_else(region=="SRME", as.double((total_area/srme_area_km2*100)), 0.0),
         prop_area = if_else(region=="WRNF", as.double((total_area/wrnf_area_km2*100)), prop_area)) %>%
  select(-c(X)) %>%
  pivot_longer(cols = c(contains("_")),
               names_to = "metric",
               values_to = "value") %>%
  mutate(metric = as.character(metric),
         metric = recode(metric,
                         "n_patch" = "Number of Patches",
                         "patch_den" = "Patch Density",
                         "total_area" = "Total area (km2)",
                         "prop_area" = "Proportion of Area")))

df$source <- factor(df$source, levels=c('Aspen10m', 'Aspen30m', 'LFEVT', 'TreeMap', 'ITSP'))
head(df)

(f8b <- ggplot(data=df, aes(y=value, x=factor(source), fill=factor(region))) +
  geom_bar(stat="identity", position="dodge", width=0.7) +
  scale_y_continuous(labels=scales::label_number_si(accuracy = 1)) +
  scale_fill_manual(values=cols) +
  labs(x="", y="Value", title="Landscape Metrics", fill="Region: ") +
  theme(axis.title.x = NULL) +
  facet_wrap(~metric, scales = "free_y") +
  theme_light(12) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1, size=11),
        axis.text.y = element_text(angle = 0, vjust=0.1, size=11),
        axis.title.y = element_text(size=12, face="italic", vjust=0.5),
        axis.title.x = element_text(size=12, face="italic", vjust=-0.5),
        plot.margin = unit(c(0.5,0.5,0.5,0.5),"cm"),
        legend.position = "top",
        legend.spacing.x = unit(0.5,"cm"),
        text = element_text(family = "Arial")))


ggsave(f8b, file = "../../figures/Figure8B_landscape_metrics.png", dpi = 300) # adjust dpi accordingly
(arr <- ggarrange(f8b,f8a,nrow=2,ncol=1,labels=c("A","B"), common.legend = T))
Warning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font databaseWarning: font family 'Arial' not found in PostScript font database

ggsave(arr, file="../../figures/Figure8_Landscape_Patch_Metrics.png", dpi=300)
Saving 10 x 10 in image

The 10-m aspen classification identified Xx more patch than reference images:


print("% Difference in number of patches: ")
[1] "% Difference in number of patches: "
a <- df %>% filter(metric=="Number of Patches",source=="Aspen10m")
b <- df %>% filter(metric=="Number of Patches",source=="LFEVT")
((b$value-a$value)/b$value)*100
[1] -135.4679 -282.3586
print("% Difference in patch density: ")
[1] "% Difference in patch density: "
a <- df %>% filter(metric=="Patch Density",source=="Aspen10m")
b <- df %>% filter(metric=="Patch Density",source=="LFEVT")
((b$value-a$value)/b$value)*100
[1] -240.8549 -366.8768
print("% Difference in total area:")
[1] "% Difference in total area:"
a <- df %>% filter(metric=="Total area (km2)",source=="Aspen10m")
aa <- df %>% filter(metric=="Total area (km2)",source=="Aspen30m")
b <- df %>% filter(metric=="Total area (km2)",source=="LFEVT")
((b$value-a$value)/b$value)*100
[1] 30.91845 18.10289
((b$value-aa$value)/b$value)*100
[1]  -9.07802 -20.41752
rm(a,aa,b)

Supplemental

Figure S1: Phenology across the SRME study region


# Spatial map(s) of key phenological metrics

breaks_dates <- as.Date(c("2020-01-01", "2021-01-01", "2022-01-01"))
breaks_numeric <- as.numeric(breaks_dates)  # Convert to numeric (days since 1970-01-01, by default)
labels_dates <- format(breaks_dates, "%Y-%m-%d")

p1 <- ggplot(data=blocks) +
  geom_sf(aes(fill=Maturity_1)) +
  scale_fill_continuous(low = "lightgreen", high = "darkgreen",
                        labels = function(x) format(as.Date(as.numeric(x), origin="1970-01-01"), "%B %d")) +
  geom_sf(data=srme,fill=NA,color="black",size=2.5) +
  labs(fill="Maturity") +
  guides(fill = guide_colourbar(barwidth = 0.5, barheight = 5.5, ticks=F,
                                 label.position = "right", title.position = "top",
                                 label.theme = element_text(angle = 0, size = 8))) +
  theme_void()

p2 <- ggplot(data=blocks) +
  geom_sf(aes(fill=Dormancy_1)) +
  scale_fill_continuous(low = "#ffffd4", high = "#993404",
                        labels = function(x) format(as.Date(as.numeric(x), origin="1970-01-01"), "%B %d")) +
  geom_sf(data=srme,fill=NA,color="black",size=2.5) +
  labs(fill="Dormancy") +
  guides(fill = guide_colourbar(barwidth = 0.5, barheight = 5.5, ticks=F,
                                 label.position = "right", title.position = "top",
                                 label.theme = element_text(angle = 0, size = 8))) +
  theme_void()

ggarrange(p1,p2)


# # Add a statistics column for legend (could do this for F1 too ...)
# blocks.m <- reshape2::melt(
#   blocks, id.vars = c("id","elevation_mn"), 
#   measure.vars = c("Greenup_1","MidGreenup_1","Maturity_1","Peak_1",
#                    "MidGreendown_1","Senescence_1","Dormancy_1"), variable.name = "metric"
# )

# Add a statistics column for legend (could do this for F1 too ...)
blocks.m <- reshape2::melt(
  blocks, id.vars = c("id","elevation_mn"), 
  measure.vars = c("Greenup_1","Maturity_1","Peak_1","Dormancy_1"), variable.name = "metric"
) %>%
  mutate(metric = as.character(metric),
         metric = as.factor(recode(metric,
                         "Greenup_1" = "Greenup",
                         "Maturity_1" = "Maturity",
                         "Peak_1" = "Peak Greenness",
                         "Dormancy_1" = "Dormancy")))
  
blocks.m$metric <- factor(blocks.m$metric, levels=c('Greenup', 'Maturity', 'Peak Greenness', 'Dormancy'))

head(blocks.m)

# Dot plot of phenology metric by elevation for all blocks

(p5 <- ggplot(data=blocks.m, aes(x=value,y=elevation_mn)) +
  geom_smooth(method="lm",colour="gray40", fill="gray70", size=0.8) +
  geom_point(size=1.2) +
  facet_wrap(~metric, scales="free_x") +
  theme_light(12) +
    labs(x="Date",y="Elevation"))


(p6 <- ggplot(data=blocks.m, aes(x=value,y=elevation_mn,color=metric)) +
  geom_point(size=1.2) +
  theme_light(12))

ROC, F1, MCC:


accmeas <- read_csv('../../data/tabular/mod/results/accmeas_prop.csv')
Rows: 1000 Columns: 18── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
dbl (18): model, prSize, bgSize, cutoff, tp, tpr, fn, tn, tnr, fp, fpr, specificity, precision, recall, f1, accuracy, gmean, mcc
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Calculate the averages for each cutoff value across model runs

accmeas.mn <- accmeas %>%
  mutate(cutoff = as.character(cutoff)) %>%
  group_by(cutoff) %>%
  summarise(
    prMn = mean(prSize,na.rm=T), # size of presence data (mean)
    prSd = sd(prSize,na.rm=T), # size of presence data (sd)
    bgMn = mean(bgSize,na.rm=T), # size of background data (mean)
    bgSd = sd(bgSize,na.rm=T), # size of background data (sd)
    fprMn = mean(fpr,na.rm=T), # False Positive Rate (mean)
    fprSd = sd(fpr,na.rm=T),
    tprMn = mean(tpr,na.rm=T), # True Positive Rate (mean)
    tprSd = sd(tpr,na.rm=T),
    precision = mean(precision,na.rm=T), # precision (mean)
    precisionSd = sd(precision,na.rm=T), 
    recall = mean(recall,na.rm=T), # recall (mean)
    recallSd = sd(recall,na.rm=T),
    f1 = mean(f1,na.rm=T), # F1 score (mean)
    f1Sd = sd(f1,na.rm=T),
    gmean = mean(gmean,na.rm=T), # Geometric Mean (mean)
    gmeanSd = sd(gmean,na.rm=T),
    mcc = mean(mcc,na.rm=T), # Matthew's Correlation Coefficient (mean)
    mccSd = sd(mcc,na.rm=T),
    accuracy = mean(accuracy,na.rm=T), # Overall accuracy (mean)
    accuracySd = sd(accuracy,na.rm=T)
  ) %>%
  ungroup() %>%
  mutate(cutoff = round(as.double(cutoff),3))

# Calculate optimum threshold based on F1 statistic

cutoffOptMn = accmeas.mn[which.max(accmeas.mn$f1),]$cutoff
precisionOptF1Mn = accmeas.mn[which.max(accmeas.mn$f1),]$precision
recallOptF1Mn = accmeas.mn[which.max(accmeas.mn$f1),]$recall
fprOptMn = accmeas.mn[which.max(accmeas.mn$f1),]$fprMn
tprOptMn = accmeas.mn[which.max(accmeas.mn$f1),]$tprMn
max_f1 <- max(accmeas.mn$f1, na.rm = TRUE)

# ROC Curve and label the AUC value (approximation)

# Get the AUC approx

# Ensure data is sorted by FPR
accmeas_mn_sorted <- accmeas.mn[order(accmeas.mn$fprMn), ]
# Compute AUC using trapz function in 'pracma'
auc_avg_approx <- trapz(accmeas_mn_sorted$fprMn, accmeas_mn_sorted$tprMn)

fs2a <- ggplot(data=accmeas) +
  geom_line(aes(x=fpr,y=tpr,color=factor(model)),linewidth=0.4) +
  scale_color_viridis_d(option="turbo") +
  geom_line(data=accmeas.mn, aes(x = fprMn, y = tprMn), color = "black", size = 0.8) +  # ROC curve average
  scale_x_continuous(limits=c(0,1)) +  # Set x axis limits from 0 to 1
  scale_y_continuous(limits=c(0,1)) +
  labs(x='False Positive Rate', y='True Positive Rate', tag="A") +
  geom_point(aes(x = fprOptMn, y = tprOptMn),
             color = "red", size = 3, shape = 19) +  # optimal threshold point
  geom_text(aes(x=fprOptMn, y=tprOptMn),
            label = paste0('Optimal threshold: ', round(cutoffOptMn,3),'\nApprox. AUC: ', round(auc_avg_approx,3)),
            nudge_x = 0.38, nudge_y = -0.08, size = 3.5) +
  coord_fixed(ratio = 1) +  # to keep the x and y axes scales same
  geom_abline(intercept = 0, slope = 1, linetype = "dashed", color = "black") +  # diagonal
  theme_light() +
  theme(legend.position = "none",
        axis.title.y = element_text(size=11,face="italic",
                                    margin = unit(c(0,0.4,0,0), "cm")),
        axis.title.x = element_text(size=11,face="italic",
                                    margin = unit(c(0.4,0,0,0), "cm")),
        axis.text = element_text(size=10),
        strip.text.x = element_text(size = 11))

fs2b <- ggplot(data=accmeas) +
  geom_line(aes(x=cutoff,y=f1,color=factor(model)),linewidth=0.4) +
  scale_color_viridis_d(option="turbo") +
  geom_line(data=accmeas.mn, aes(x=cutoff, y = f1), color = "black", size = 0.8) +  # ROC curve average
  # geom_vline(xintercept=0.424, linetype="dashed", color="black") +
  geom_point(aes(x=cutoffOptMn, y=max_f1),
             color = "red", size = 3, shape = 19) +
  geom_text(aes(x=cutoffOptMn, y=max_f1),
            label = paste0('Optimal threshold: ', round(cutoffOptMn,3)),
            nudge_x = 0.0, nudge_y = 0.08, size = 3.5) +
  scale_x_continuous(limits=c(0,1)) +  # Set x axis limits from 0 to 1
  scale_y_continuous(limits=c(0,1)) +
  labs(x='Threshold', y='F1 Score', tag="B") +
  coord_fixed(ratio = 1) +  # to keep the x and y axes scales same
  theme_light() +
  theme(legend.position = "none",
        axis.title.y = element_text(size=11,face="italic",
                                    margin = unit(c(0,0.4,0,0), "cm")),
        axis.title.x = element_text(size=11,face="italic",
                                    margin = unit(c(0.4,0,0,0), "cm")),
        axis.text = element_text(size=10),
        strip.text.x = element_text(size = 11))

(fs2 <- ggarrange(fs2a,fs2b))

ggsave(fs2, file="../../figures/FigureS2_AUC_F1Max.png", dpi=300)


rm(fs2,fs2a,fs2b,accmeas_mn_sorted,auc_avg_approx)

Table S1: Performance metrics for the optimum cutoff value

Create a pretty table.


library(flextable, quietly = T)

# Get the best F1 score for each model run
accmeas.best <- accmeas %>% 
  mutate(model = as.factor(model)) %>%
  group_by(model) %>% 
  top_n(1,f1) %>%
  ungroup() %>%
  mutate(model_iter = row_number()) %>%
  select(model,prSize,bgSize,tpr,precision,recall,f1,cutoff)

head(accmeas.best,10)

# Fix names and add units
names(accmeas.best) <- c("Model Seed",
                         "# of Presence",
                         "# of Background",
                         "True Positive Rate",
                         "Precision",
                         "Recall",
                         "F1-Score",
                         "Threshold")

# Set font name for table
fontname <- "Times New Roman"

# Create the flextable
(ft1 <- flextable(accmeas.best) %>%
 font(fontname = fontname, part = "all") %>%
 autofit() %>% fit_to_width(6.5))

Model Seed

# of Presence

# of Background

True Positive Rate

Precision

Recall

F1-Score

Threshold

847

2,901

25,590

0.8700448

0.9121793

0.8700448

0.8906140

0.3939394

991

6,270

33,755

0.8848485

0.9202189

0.8848485

0.9021872

0.2727273

343

7,868

31,484

0.9246314

0.9192570

0.9246314

0.9219364

0.4242424

197

8,184

38,450

0.8925953

0.9248006

0.8925953

0.9084126

0.3434343

783

6,175

29,167

0.9206478

0.9243902

0.9206478

0.9225152

0.5353535

9

4,467

17,982

0.9131408

0.9575117

0.9131408

0.9348000

0.6565657

283

1,792

18,536

0.8683036

0.9152941

0.8683036

0.8911798

0.5353535

777

5,743

24,471

0.9254745

0.9311493

0.9254745

0.9283032

0.3131313

588

4,441

25,921

0.9119568

0.9414226

0.9119568

0.9264555

0.5050505

708

5,958

31,742

0.9026519

0.9380778

0.9026519

0.9200240

0.4343434

print(ft1, preview = "docx")

# Write to a CSV
write_csv(accmeas.best, "../../figures/TableS1_Accuracy_MaxF1.csv")

Clean up!

LS0tCnRpdGxlOiAiRmlndXJlcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3IgaW5jbHVkZT1GfQprbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICd+L0xpYnJhcnkvQ2xvdWRTdG9yYWdlL09uZURyaXZlLVBlcnNvbmFsL21jb29rL2FzcGVuLWZpcmUnKQpzb3VyY2UoJ3NldHVwLlInKQpgYGAKCiMjIFNUVURZIEFSRUEKCmBgYHtyfQpnZ3Bsb3QoKSArCiAgZ2VvbV9zZihkYXRhPXNybWUpICsKICBnZW9tX3NmKGRhdGE9d3JuZiwgZmlsbD0iZGFya2dyZXkiKSArCiAgY29vcmRfc2YoY3JzPSJFUFNHOjMyNjEzIikgKwogIHRoZW1lX2J3KDExKQpgYGAKCiMjIEZpZ3VyZSAxOiBTdXJmYWNlIFJlZmxlY3RhbmNlIC8gU3BlY3RyYWwgUmVzcG9uc2UKCmBgYHtyfQpoZWFkKHRzKQpgYGAKClRpZHkgdGhlIHRpbWUtc2VyaWVzIGRhdGEuCgoxLiBSZW1vdmUgY2xvdWQtY29udGFtaW5hdGVkIHBpeGVscywKMi4gUGl2b3QgdGhlIHRhYmxlIHRvIGdhdGhlciBiYW5kcywKMy4gR2VuZXJhdGUgbWVhbi9tZWRpYW4vc3RkZXYgb2YgcmVmbGVjdGFuY2UgYnkgaW1hZ2UgZGF0ZSwKNC4gQ2FsY3VsYXRlIHdlZWtseSBzdW1tYXJpZXMKCkZpbHRlciB1c2luZyB0aGUgcGl4ZWwgY2xvdWQgcHJvYmFiaWxpdHksIHNjZW5lIGNsYXNzaWZpY2F0aW9uLCBhbmQgcmVtb3ZlIGVycm9uZW91c2x5IGhpZ2ggcmVmbGVjdGFuY2UgdmFsdWVzOgoKYGBge3IgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9My41fQoKdHNwIDwtIHRzICU+JQogIGZpbHRlcigKICAgIHByb2JhYmlsaXR5IDwgNTEsICMgbGVzcyB0aGFuIDUxJSBjbG91ZCBwcm9iYWJpbGl0eQogICAgISBTQ0wgPiA3ICYgU0NMIDw9IDEwLCAjIHJlbW92ZSBwb2ludHMgbGFiZWxlZCBhcyBjbG91ZAogICAgQjggPCA1MDAwICMgcmVtb3ZlIHBvaW50cyB3aXRoIHZlcnkgaGlnaCBuZWFyLWluZnJhcmVkIHJlZmxlY3RhbmNlCiAgKSAlPiUKICAjIGFkZCB0aGUgbW9udGggYXMgYSBjb2x1bW4KICBtdXRhdGUobW9udGggPSBtb250aChpbWFnZV9kYXRlLCBsYWJlbD1UUlVFLCBhYmJyPVRSVUUpKQoKdHNwICU+JQogIGdyb3VwX2J5KGltYWdlX2RhdGUpICU+JQogIHN1bW1hcml6ZShiYW5kID0gbWVkaWFuKEI4KSkgJT4lCiAgZ2dwbG90KGFlcyh4PWltYWdlX2RhdGUseT1iYW5kKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0xLjIpICsKICBnZW9tX3Ntb290aChtZXRob2Q9ImdhbSIpICsKICB0aGVtZV9idygxNCkKCmdncGxvdChkYXRhPXRzcCwgYWVzKHg9QjgsIHk9bW9udGgpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfYncoKQoKcm0odHMpCgpgYGAKCk5vdyBwaXZvdCB0aGUgdGFibGUgbG9uZ2VyOgoKYGBge3J9Cgp0c3AgPC0gdHNwICU+JQogIHNlbGVjdChjKHN0YXJ0c193aXRoKCJCIiksaW1hZ2VfZGF0ZSwKICAgICAgICAgICBTTEFWSSxORFJFLE5ETUksQ2hsUkUsSVJFQ0kpKSAlPiUKICBncm91cF9ieShpbWFnZV9kYXRlKSAlPiUKICBzdW1tYXJpemVfYWxsKGxpc3QobWVkaWFuKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKAogICAgY29scyA9IC1pbWFnZV9kYXRlLAogICAgbmFtZXNfdG89ImJhbmQiLAogICAgdmFsdWVzX3RvPSJyZWZsIgogICkgJT4lCiAgIyBhZGQgYSBtb250aCBhbmQgd2VlayBsYWJlbAogIG11dGF0ZSgKICAgIG1vbnRoID0gbW9udGgoaW1hZ2VfZGF0ZSwgbGFiZWw9VFJVRSwgYWJicj1UUlVFKSwKICAgIHdlZWsgPSBpc293ZWVrKGltYWdlX2RhdGUpLAogICAgd2VlazIgPSBjdXQuRGF0ZShpbWFnZV9kYXRlLCBicmVha3M9IjIgd2VlayIsIGxhYmVscz1GQUxTRSkKICApCgpoZWFkKHRzcCkKCmBgYAoKUGxvdCBvZiBtZWRpYW4gZGFpbHkgb2JzZXJ2YXRpb25zOgoKYGBge3IgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9OX0KIyBSZW9yZGVyIGJhbmQgZmFjdG9ycwp0c3AkYmFuZCA8LSBmYWN0b3IodHNwJGJhbmQsIAogICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiQjIiLCJCMyIsIkI0IiwiQjUiLCJCNiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJCNyIsIkI4IiwiQjhBIiwiQjExIiwiQjEyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNobFJFIiwiSVJFQ0kiLCJORE1JIiwiTkRSRSIsIlNMQVZJIikpCgp0c3AgJT4lCiAgZmlsdGVyKHN0cl9kZXRlY3QoYmFuZCwiQiIpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9aW1hZ2VfZGF0ZSx5PXJlZmwsY29sb3I9ZmFjdG9yKGJhbmQpKSkgKwogIGdlb21fbGluZShsaW5ld2lkdGg9MC40KSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19kKG9wdGlvbj0idHVyYm8iKSArCiAgbGFicyh4PSJBY3F1aXNpdGlvbiBEYXRlIix5PSJSZWZsZWN0YW5jZSIsY29sb3I9IlMyIE1TSSBCYW5kIikgKwogIHRoZW1lX2J3KDE0KSArCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTEsZmFjZT0iaXRhbGljIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAsMC40LDAsMCksICJjbSIpKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMSxmYWNlPSJpdGFsaWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMC40LDAsMCwwKSwgImNtIikpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMSkpCmBgYAoKIyBGaWd1cmUgMzogU3BlY3RyYWwgUmVzcG9uc2Ugb2YgQXNwZW4gRm9yZXN0IFByZXNlbmNlIERhdGEKCkdhdGhlciB0aGUgc2Vhc29uYWwgY29tcG9zaXRlIHN0YXJ0IGFuZCBlbmQgZGF0ZXM6CgpgYGB7cn0KIyBTdW1tZXIKKHN0YXJ0X3N1bW1lciA8LSB3ZWVrKGFzLkRhdGUoIjIwMTktMDYtMDEiKSkpCihlbmRfc3VtbWVyIDwtIHdlZWsoYXMuRGF0ZSgiMjAxOS0wOS0xNCIpKSkKIyBBdXR1bW4KKHN0YXJ0X2F1dHVtbiA8LSB3ZWVrKGFzLkRhdGUoIjIwMTktMDktMTYiKSkpCihlbmRfYXV0dW1uIDwtIHdlZWsoYXMuRGF0ZSgiMjAxOS0xMS0zMCIpKSkKYGBgCgpHZW5lcmF0ZSB0aGUgd2Vla2x5IG1lZGlhbiByZWZsZWN0YW5jZS4KCmBgYHtyIHdhcm5pbmc9RiwgbWVzc2FnZT1GLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD05fQoKIyBMaXN0IGZvciBiYW5kIGNvbG9ycwoKYmFuZF9jb2xvcnMgPC0gYygKICAiQjIiICA9ICIjMUU5MEZGIiwgICMgQmx1ZTogRG9kZ2VyIEJsdWUKICAiQjMiICA9ICIjMDBGRjdGIiwgICMgR3JlZW46IFNwcmluZyBHcmVlbgogICJCNCIgID0gIiNGRjAwMDAiLCAgIyBSZWQ6IFB1cmUgUmVkCiAgIkI1IiAgPSAiI0ZGQTA3QSIsICAjIFJlZCBFZGdlOiBMaWdodCBTYWxtb24KICAiQjYiICA9ICIjRkY4QzAwIiwgICMgTklSOiBEYXJrIE9yYW5nZQogICJCNyIgID0gIiNEMjY5MUUiLCAgIyBOSVI6IENob2NvbGF0ZQogICJCOCIgID0gIiNGRkQ3MDAiLCAgIyBOSVI6IEdvbGQKICAiQjhBIiA9ICIjQjg4NjBCIiwgICMgTklSOiBEYXJrIEdvbGRlbnJvZAogICJCMTEiID0gIiMwMDhCOEIiLCAgIyBTV0lSOiBEYXJrIEN5YW4gKGRhcmsgc2hhZGUgb2YgdGVhbCkKICAiQjEyIiA9ICIjODAwMDgwIiAgICMgU1dJUjogUHVycGxlCikKCgojIEdyb3VwIGJ5IHdlZWssIGNhbGN1bGF0ZSB0aGUgbWVhbiwgcGxvdAoKZjNhIDwtIHRzcCAlPiUKICBmaWx0ZXIoc3RyX2RldGVjdChiYW5kLCJCIikpICU+JQogIGdyb3VwX2J5KGJhbmQsd2VlaykgJT4lCiAgc3VtbWFyaXplKHJlZmwgPSBtZWFuKHJlZmwpKSAlPiUKICAKICBnZ3Bsb3QoYWVzKHg9d2Vlayx5PXJlZmwsY29sb3I9ZmFjdG9yKGJhbmQpKSkgKwogIGdlb21fbGluZShsaW5ld2lkdGg9MC42KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGJhbmRfY29sb3JzKSArCiAgbGFicyh4PSJBY3F1aXNpdGlvbiBXZWVrIix5PSJSZWZsZWN0YW5jZSIsY29sb3I9TlVMTCkgKwogIHRoZW1lX2J3KDExKSArCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTEsZmFjZT0iaXRhbGljIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAsMC40LDAsMCksICJjbSIpKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMSxmYWNlPSJpdGFsaWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMC40LDAsMCwwKSwgImNtIikpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTgpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTgpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4yLDAuODUpLAogICAgICAgIGxlZ2VuZC5kaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0id2hpdGUiLCBjb2xvcj0iYmxhY2siKSwKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygxLjIsMC41LDEuMiwwLjUpLCAnbGluZXMnKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJBcmlhbCIpKSArCiAgYW5ub3RhdGUoJ3JlY3QnLCB4bWluPXN0YXJ0X3N1bW1lciwgeG1heD1lbmRfYXV0dW1uLCB5bWluPTAsIHltYXg9NDAwMCwgYWxwaGE9LjMsIGZpbGw9J2dyYXknKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PXN0YXJ0X2F1dHVtbiwgbGluZXR5cGU9ImRvdHRlZCIsIGx3ZD0wLjgpCmYzYQpgYGAKCkZpZ3VyZSAxQjogVGltZS1zZXJpZXMgY2hhcnRzIG9mIHRoZSBzcGVjdHJhbCBpbmRpY2VzOgoKYGBge3IgbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CgojIEFsbCBiYW5kcwoKdHNwICU+JQogIGdyb3VwX2J5KGJhbmQsd2VlaykgJT4lCiAgc3VtbWFyaXplKHJlZmwgPSBtZWFuKHJlZmwpKSAlPiUKICBnZ3Bsb3QoYWVzKHg9d2VlaywgeT1yZWZsLCBncm91cD0xKSkgKwogIGdlb21fbGluZSgpICsKICBhbm5vdGF0ZSgncmVjdCcsIHhtaW49MjIsIHhtYXg9NDgsIHltaW49MCwgeW1heD1JbmYsIGFscGhhPS4zLCBmaWxsPSdncmF5JykgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdD0zNywgbGluZXR5cGU9ImRvdHRlZCIpICsKICBmYWNldF93cmFwKC4gfiBiYW5kLCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTgsZmFjZT0iaXRhbGljIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAsMC40LDAsMCksICJjbSIpKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT04LGZhY2U9Iml0YWxpYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygwLjQsMCwwLDApLCAiY20iKSksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9NyksCiAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkKCiMgU3BlY3RyYWwgaW5kaWNlcwoKZjNiIDwtIHRzcCAlPiUKICBmaWx0ZXIoIXN0cl9kZXRlY3QoYmFuZCwiQiIpKSAlPiUKICBncm91cF9ieShiYW5kLHdlZWspICU+JQogIHN1bW1hcml6ZShyZWZsID0gbWVhbihyZWZsKSkgJT4lCiAgZ2dwbG90KGFlcyh4PXdlZWssIHk9cmVmbCwgZ3JvdXA9MSkpICsKICBnZW9tX2xpbmUobGluZXdpZHRoPTAuNikgKwogIGxhYnMoeD0iQWNxdWlzaXRpb24gV2VlayIseT0iUmVmbGVjdGFuY2UiKSArCiAgYW5ub3RhdGUoJ3JlY3QnLCB4bWluPXN0YXJ0X3N1bW1lciwgeG1heD1lbmRfYXV0dW1uLCB5bWluPTAsIHltYXg9SW5mLCBhbHBoYT0uMywgZmlsbD0nZ3JheScpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9c3RhcnRfYXV0dW1uLCBsaW5ldHlwZT0iZG90dGVkIiwgbHdkPTAuOCkgKwogIGZhY2V0X3dyYXAoLiB+IGJhbmQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHRoZW1lX2xpZ2h0KDExKSArCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTEsZmFjZT0iaXRhbGljIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAsMC40LDAsMCksICJjbSIpKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMSxmYWNlPSJpdGFsaWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMC40LDAsMCwwKSwgImNtIikpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwKICAgICAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygxLjIsMC41LDEuMiwwLjUpLCAnbGluZXMnKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJBcmlhbCIpKQpmM2IKCmBgYAoKRmlndXJlIDNDOiBCb3hwbG90IG9mIHNlYXNvbmFsIGNvbXBvc2l0ZXM6CgpgYGB7cn0KCiMgUmVvcmRlciBiYW5kIGZhY3RvcnMKdHNwJGJhbmQgPC0gZmFjdG9yKHRzcCRiYW5kLCAKICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGMoIkIyIiwiQjMiLCJCNCIsIkI1IiwiQjYiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQjciLCJCOCIsIkI4QSIsIkIxMSIsIkIxMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDaGxSRSIsIklSRUNJIiwiTkRNSSIsIk5EUkUiLCJTTEFWSSIpKQoKY29scyA8LSBjKAogICJTdW1tZXIiID0gIiM4N0NFRUIiLCAKICAiQXV0dW1uIiA9ICIjREFBNTIwIgopCgpzZWFzb25hbCA8LSB0c3AgJT4lCiAgbXV0YXRlKHNlYXNvbiA9IGlmX2Vsc2Uod2Vlaz49MjImd2Vlazw9MzcsIlN1bW1lciIsIm5hIiksCiAgICAgICAgIHNlYXNvbiA9IGlmX2Vsc2Uod2Vlaz49Mzcmd2Vlazw9NDgsIkF1dHVtbiIsc2Vhc29uKSkgJT4lCiAgZmlsdGVyKHNlYXNvbiE9Im5hIikKCnNlYXNvbmFsJHNlYXNvbiA8LSBmYWN0b3Ioc2Vhc29uYWwkc2Vhc29uLCBsZXZlbHMgPSBjKCJTdW1tZXIiLCJBdXR1bW4iKSkKICAKZjNjIDwtIHNlYXNvbmFsICU+JQogIGZpbHRlcihzdHJfZGV0ZWN0KGJhbmQsIkIiKSkgJT4lCiAgZ2dwbG90KGFlcyh4PWJhbmQseT1yZWZsLGZpbGw9c2Vhc29uKSkgKwogIGdlb21fYm94cGxvdChvdXRsaWVyLnNpemUgPSAwLjUsIG91dGxpZXIuY29sb3IgPSAiZ3JleTMwIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbHMpICsKICB0aGVtZV9idygxNikgKwogIGxhYnMoeD0iU2VudGluZWwtMiBNU0kgQmFuZCIseT0iUmVmbGVjdGFuY2UiKSArCiAgdGhlbWUoYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemU9MTEsZmFjZT0iaXRhbGljIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAsMC40LDAsMCksICJjbSIpKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMSxmYWNlPSJpdGFsaWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMC40LDAsMCwwKSwgImNtIikpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEwKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoMS4yLDAuNSwxLjIsMC41KSwgJ2xpbmVzJyksCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiQXJpYWwiKSkKZjNjCgpgYGAKCkZpZ3VyZSAxRDogU2Vhc29uYWwgZGlmZmVyZW5jZXMgaW4gdGhlIHNwZWN0cmFsIGluZGljZXMKCmBgYHtyfQoKZjNkIDwtIHNlYXNvbmFsICU+JQogIGZpbHRlcighc3RyX2RldGVjdChiYW5kLCJCIikpICU+JQogIGdncGxvdChhZXMoeT1yZWZsKSkgKwogIGdlb21fYm94cGxvdChhZXMoZmlsbD1zZWFzb24pKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29scykgKwogIGZhY2V0X3dyYXAoLiB+IGJhbmQsIHNjYWxlcyA9ICJmcmVlIikgKwogIHRoZW1lX2J3KDE0KSArCiAgbGFicyhmaWxsPSJTZWFzb24iLHk9IlZhbHVlIikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMSxmYWNlPSJpdGFsaWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMCwwLjQsMCwwKSwgImNtIikpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTExLGZhY2U9Iml0YWxpYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygwLjQsMCwwLDApLCAiY20iKSksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLAogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC44NSwwLjIpLAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTE2KSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE1KSwKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygxLjIsMC41LDEuMiwwLjUpLCAnbGluZXMnKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJBcmlhbCIpKQpmM2QKCmBgYAoKQ29tYmluZSB0aGUgcGxvdHM6CgpgYGB7ciBmaWcud2lkdGg9MTQsIGZpZy5oZWlnaHQ9OCwgbWVzc2FnZT1GfQoKIyBBcnJhbmdlIGluIGEgbXVsdGktcGFuZWwgcGxvdAoKZjMgPC0gZ2dhcnJhbmdlKGYzYSxmM2IsZjNjLGYzZCwgbnJvdz0yLG5jb2w9Mix3aWR0aHM9YygxLCAwLjc1KSwgbGFiZWxzID0gYygiQSIsICJCIiwgIkMiLCAiRCIpKQpmMwoKIyBTYXZlIGl0IG91dAoKZ2dzYXZlKGYzLCBmaWxlID0gIi4uLy4uL2ZpZ3VyZXMvRmlndXJlM19TcGVjdHJhbFJlc3BvbnNlLnBuZyIsCiAgICAgICBkcGkgPSAzMDAsIGJnPSJ3aGl0ZSIpICMgYWRqdXN0IGRwaSBhY2NvcmRpbmdseQoKYGBgCgpWZXJzaW9uIDI6CgpgYGB7ciBmaWcud2lkdGg9MTQsIGZpZy5oZWlnaHQ9OH0KCmYzXyA8LSBnZ2FycmFuZ2UoZjNhLGdnYXJyYW5nZShmM2MsZjNkLG5yb3c9MSxuY29sPTIpLAogICAgICAgICAgICAgICAgICBuY29sPTEsd2lkdGhzPWMoMSwgMC43NSksCiAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkEiLCAiQiIsICJDIikpCmYzXwoKZ2dzYXZlKGYzXywgZmlsZSA9ICIuLi8uLi9maWd1cmVzL0ZpZ3VyZTNfU3BlY3RyYWxSZXNwb25zZV92Mi5wbmciLAogICAgICAgZHBpID0gMzAwLCBiZz0id2hpdGUiKSAjIGFkanVzdCBkcGkgYWNjb3JkaW5nbHkKCmBgYAoKQ2xlYW4gdXAgdGhlIHRpbWUtc2VyaWVzIC8gc3BlY3RyYWwgcmVzcG9uc2UgZGF0YToKCmBgYHtyfQpybShmMyxmM18sZjNhLGYzYixmM2MsZjNkLHNlYXNvbmFsLHRzcCkKZ2MoKQpgYGAKCiMjIEZpZ3VyZSA0OiBNb2RlbCBhY2N1cmFjeSBhbmQgZmVhdHVyZSBpbXBvcnRhbmNlIHBsb3QKCkJlc3QgUGVyZm9ybWluZyBNb2RlbDoKCgpQbG90IHRoZSBBVUMtUFIgYW5kIEFVQy1ST0MuCgpgYGB7cn0KZ2xpbXBzZShhY2NtZWFzKQpgYGAKCkNhbGN1bGF0ZSB0aGUgbW9kZWwgYXZlcmFnZXMgdXNpbmcgdGhlIG9wdGltdW0gY3V0b2ZmIHZhbHVlOgoKYGBge3J9CiMgV2l0aG91dCB0YWtpbmcgdGhlIGF2ZXJhZ2UKCnByaW50KCJ+fn5+flRvdGFsIChub3QgYXZlcmFnZWluZyl+fn5+fiIpCgooY3V0b2ZmT3B0RjEgPSBhY2NtZWFzW3doaWNoLm1heChhY2NtZWFzJGYxKSxdJGN1dG9mZikKKHByZWNpc2lvbk9wdEYxID0gYWNjbWVhc1t3aGljaC5tYXgoYWNjbWVhcyRmMSksXSRwcmVjaXNpb24pCihyZWNhbGxPcHRGMSA9IGFjY21lYXNbd2hpY2gubWF4KGFjY21lYXMkZjEpLF0kcmVjYWxsKQooZnByT3B0ID0gYWNjbWVhc1t3aGljaC5tYXgoYWNjbWVhcyRmMSksXSRmcHIpCih0cHJPcHQgPSBhY2NtZWFzW3doaWNoLm1heChhY2NtZWFzJGYxKSxdJHRwcikKCiMgV2l0aCB0aGUgYWdncmVnYXRpb24vYXZlcmFnaW5nIGFjcm9zcyBtb2RlbHMgYW5kIHRocmVzaG9sZCB2YWx1ZXMKCiMgQ2FsY3VsYXRlIHRoZSBhdmVyYWdlcyBmb3IgZWFjaCBjdXRvZmYgdmFsdWUgYWNyb3NzIG1vZGVsIHJ1bnMKCmFjY21lYXMubW4gPC0gYWNjbWVhcyAlPiUKICBtdXRhdGUoY3V0b2ZmID0gYXMuY2hhcmFjdGVyKGN1dG9mZikpICU+JQogIGdyb3VwX2J5KGN1dG9mZikgJT4lCiAgc3VtbWFyaXNlKAogICAgcHJNbiA9IG1lYW4ocHJTaXplLG5hLnJtPVQpLCAjIHNpemUgb2YgcHJlc2VuY2UgZGF0YSAobWVhbikKICAgIHByU2QgPSBzZChwclNpemUsbmEucm09VCksICMgc2l6ZSBvZiBwcmVzZW5jZSBkYXRhIChzZCkKICAgIGJnTW4gPSBtZWFuKGJnU2l6ZSxuYS5ybT1UKSwgIyBzaXplIG9mIGJhY2tncm91bmQgZGF0YSAobWVhbikKICAgIGJnU2QgPSBzZChiZ1NpemUsbmEucm09VCksICMgc2l6ZSBvZiBiYWNrZ3JvdW5kIGRhdGEgKHNkKQogICAgZnByTW4gPSBtZWFuKGZwcixuYS5ybT1UKSwgIyBGYWxzZSBQb3NpdGl2ZSBSYXRlIChtZWFuKQogICAgZnByU2QgPSBzZChmcHIsbmEucm09VCksCiAgICB0cHJNbiA9IG1lYW4odHByLG5hLnJtPVQpLCAjIFRydWUgUG9zaXRpdmUgUmF0ZSAobWVhbikKICAgIHRwclNkID0gc2QodHByLG5hLnJtPVQpLAogICAgcHJlY2lzaW9uID0gbWVhbihwcmVjaXNpb24sbmEucm09VCksICMgcHJlY2lzaW9uIChtZWFuKQogICAgcHJlY2lzaW9uU2QgPSBzZChwcmVjaXNpb24sbmEucm09VCksIAogICAgcmVjYWxsID0gbWVhbihyZWNhbGwsbmEucm09VCksICMgcmVjYWxsIChtZWFuKQogICAgcmVjYWxsU2QgPSBzZChyZWNhbGwsbmEucm09VCksCiAgICBmMSA9IG1lYW4oZjEsbmEucm09VCksICMgRjEgc2NvcmUgKG1lYW4pCiAgICBmMVNkID0gc2QoZjEsbmEucm09VCksCiAgICBnbWVhbiA9IG1lYW4oZ21lYW4sbmEucm09VCksICMgR2VvbWV0cmljIE1lYW4gKG1lYW4pCiAgICBnbWVhblNkID0gc2QoZ21lYW4sbmEucm09VCksCiAgICBtY2MgPSBtZWFuKG1jYyxuYS5ybT1UKSwgIyBNYXR0aGV3J3MgQ29ycmVsYXRpb24gQ29lZmZpY2llbnQgKG1lYW4pCiAgICBtY2NTZCA9IHNkKG1jYyxuYS5ybT1UKSwKICAgIGFjY3VyYWN5ID0gbWVhbihhY2N1cmFjeSxuYS5ybT1UKSwgIyBPdmVyYWxsIGFjY3VyYWN5IChtZWFuKQogICAgYWNjdXJhY3lTZCA9IHNkKGFjY3VyYWN5LG5hLnJtPVQpCiAgKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGN1dG9mZiA9IHJvdW5kKGFzLmRvdWJsZShjdXRvZmYpLDMpKQoKIyBDYWxjdWxhdGUgb3B0aW11bSB0aHJlc2hvbGQgYmFzZWQgb24gRjEgc3RhdGlzdGljCgpjdXRvZmZPcHRNbiA9IGFjY21lYXMubW5bd2hpY2gubWF4KGFjY21lYXMubW4kZjEpLF0kY3V0b2ZmCnByZWNpc2lvbk9wdEYxTW4gPSBhY2NtZWFzLm1uW3doaWNoLm1heChhY2NtZWFzLm1uJGYxKSxdJHByZWNpc2lvbgpyZWNhbGxPcHRGMU1uID0gYWNjbWVhcy5tblt3aGljaC5tYXgoYWNjbWVhcy5tbiRmMSksXSRyZWNhbGwKZnByT3B0TW4gPSBhY2NtZWFzLm1uW3doaWNoLm1heChhY2NtZWFzLm1uJGYxKSxdJGZwck1uCnRwck9wdE1uID0gYWNjbWVhcy5tblt3aGljaC5tYXgoYWNjbWVhcy5tbiRmMSksXSR0cHJNbgptYXhfZjEgPC0gbWF4KGFjY21lYXMubW4kZjEsIG5hLnJtID0gVFJVRSkKCmBgYAoKYGBge3J9CiMgRjEgYmFzZWQKcHJpbnQoIkYxLWJhc2VkIGFjY3VyYWN5IG1ldHJpY3M6IikKcGFzdGUwKCJGMSBTY29yZTogIiwoZjFPcHQgPSBhY2NtZWFzLm1uW3doaWNoLm1heChhY2NtZWFzLm1uJGYxKSxdJGYxKSkKcGFzdGUwKCJPdmVyYWxsIEFjY3VyYWN5OiAiLChvYU9wdCA9IGFjY21lYXMubW5bd2hpY2gubWF4KGFjY21lYXMubW4kZjEpLF0kYWNjdXJhY3kpKQpwYXN0ZTAoIlByZWNpc2lvbjogIiwocHJlY09wdCA9IGFjY21lYXMubW5bd2hpY2gubWF4KGFjY21lYXMubW4kZjEpLF0kcHJlY2lzaW9uKSkKcGFzdGUwKCJSZWNhbGw6ICIsKHJlY09wdCA9IGFjY21lYXMubW5bd2hpY2gubWF4KGFjY21lYXMubW4kZjEpLF0kcmVjYWxsKSkKcGFzdGUwKCJDdXRvZmY6ICIsKHRocmVzaE9wdCA9IGFjY21lYXMubW5bd2hpY2gubWF4KGFjY21lYXMubW4kZjEpLF0kY3V0b2ZmKSkKCiMgTWF0aGV3cyBDb3JyZWxhdGlvbiBDb2VmZmljaWVudApwcmludCgiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIikKcHJpbnQoIk1DQy1iYXNlZCBhY2N1cmFjeSBtZXRyaWNzOiIpCnBhc3RlMCgiTUNDOiAiLChtY2NPcHQgPSBhY2NtZWFzLm1uW3doaWNoLm1heChhY2NtZWFzLm1uJG1jYyksXSRtY2MpKQpwYXN0ZTAoIk92ZXJhbGwgQWNjdXJhY3k6ICIsKG9hT3B0bWNjID0gYWNjbWVhcy5tblt3aGljaC5tYXgoYWNjbWVhcy5tbiRtY2MpLF0kYWNjdXJhY3kpKQpwYXN0ZTAoIlByZWNpc2lvbjogIiwocHJlY09wdG1jYyA9IGFjY21lYXMubW5bd2hpY2gubWF4KGFjY21lYXMubW4kbWNjKSxdJHByZWNpc2lvbikpCnBhc3RlMCgiUmVjYWxsOiAiLChyZWNPcHRtY2MgPSBhY2NtZWFzLm1uW3doaWNoLm1heChhY2NtZWFzLm1uJG1jYyksXSRyZWNhbGwpKQpwYXN0ZTAoIkN1dG9mZjogIiwodGhyZXNoT3B0bWNjID0gYWNjbWVhcy5tblt3aGljaC5tYXgoYWNjbWVhcy5tbiRtY2MpLF0kY3V0b2ZmKSkKYGBgCgpQbG90IHRoZSBtb2RlbCBhY2N1cmFjeSByZXN1bHRzIGZvciB0aGUgb3B0aW11bSB0aHJlc2hvbGQuCgpgYGB7cn0KCiMgR2V0IHRoZSBiZXN0IEYxIHNjb3JlIGZvciBlYWNoIG1vZGVsIHJ1bgphY2NtZWFzLmJlc3QgPC0gYWNjbWVhcyAlPiUgCiAgZ3JvdXBfYnkoZmFjdG9yKG1vZGVsKSkgJT4lIHRvcF9uKDEsZjEpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUobW9kZWxfaXRlciA9IHJvd19udW1iZXIoKSkKCnByaW50KHBhc3RlMCgiQ3V0b2ZmOiBNZWFuID0gIixyb3VuZChtZWFuKGFjY21lYXMuYmVzdCRjdXRvZmYpLDMpLCI7IFN0YW5kYXJkIERldmlhdGlvbjogIixyb3VuZChzZChhY2NtZWFzLmJlc3QkY3V0b2ZmKSwzKSkpCnByaW50KHBhc3RlMCgiRjEgU2NvcmU6IE1lYW4gPSAiLHJvdW5kKG1lYW4oYWNjbWVhcy5iZXN0JGYxKSwzKSwiOyBTdGFuZGFyZCBEZXZpYXRpb246ICIscm91bmQoc2QoYWNjbWVhcy5iZXN0JGYxKSwzKSkpCgpgYGAKCkZpZ3VyZSA0QTogTW9kZWwgQWNjdXJhY3kgKEYxIGFuZCBPQSkKCmBgYHtyIG1lc3NhZ2U9Riwgd2FybmluZz1GfQoKY29scyA8LSBjKCJGMSBTY29yZSI9IiMxZjc4YjQiLCJPdmVyYWxsIEFjY3VyYWN5Ij0iZ3JheTc1IikKCmY0YSA8LSBnZ3Bsb3QoZGF0YT1hY2NtZWFzLmJlc3QpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MC45NzI3NjA5NzMwOTY4MjQsbGluZXR5cGU9ImRhc2hlZCIsY29sb3I9ImdyYXk4NSIpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MC45MTAzMzk0NzczNTU2MjksbGluZXR5cGU9ImRhc2hlZCIsY29sb3I9IiMxZjc4YjQiKSArCiAgZ2VvbV9saW5lKGFlcyh4PWZhY3Rvcihtb2RlbF9pdGVyKSx5PWFjY3VyYWN5LGdyb3VwPTEpLGNvbG9yPSJncmF5NjUiKSArCiAgZ2VvbV9saW5lKGFlcyh4PWZhY3Rvcihtb2RlbF9pdGVyKSx5PWYxLGdyb3VwPTEpLGNvbG9yPSIjMWY3OGI0IikgKwogIGdlb21fcG9pbnQoYWVzKHg9ZmFjdG9yKG1vZGVsX2l0ZXIpLHk9ZjEsc2l6ZT1mMSksIGNvbG9yPSIjMWY3OGI0IikgKwogIGdlb21fcG9pbnQoYWVzKHg9ZmFjdG9yKG1vZGVsX2l0ZXIpLHk9YWNjdXJhY3ksc2l6ZT1hY2N1cmFjeSksIGNvbG9yPSJncmF5NjUiKSArCiAgc2NhbGVfc2l6ZShyYW5nZSA9IGMoMyw2KSkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLjg1LCAxKSkgKwogIGxhYnMoeD0iTW9kZWwgSXRlcmF0aW9uIiwgeT0iU2NvcmUiLCB0YWc9IkEiKSArCiAgYW5ub3RhdGUoInRleHQiLCB4ID0gMywgeSA9IDAuOTksIGxhYmVsID0gcGFzdGUoIkF2ZXJhZ2UgT3ZlcmFsbCBBY2N1cmFjeTogIiwgcm91bmQob2FPcHQsIDIpKSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IDIuNiwgeSA9IDAuODgsIGxhYmVsID0gcGFzdGUoIkF2ZXJhZ2UgRjEgU2NvcmU6ICIsIHJvdW5kKGYxT3B0LCAyKSkpICsKICB0aGVtZV9idygpICsKICBndWlkZXMoc2l6ZT0ibm9uZSIpICsKICB0aGVtZSgKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLjIsMC4yLDAuMiwwLjIpLCAnbGluZXMnKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMSxmYWNlPSJpdGFsaWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMCwwLjQsMCwwKSwgImNtIikpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTExLGZhY2U9Iml0YWxpYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygwLjQsMCwwLDApLCAiY20iKSksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLAogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkFyaWFsIikpCmY0YQoKZ2dzYXZlKGY0YSwgZmlsZSA9ICIuLi8uLi9maWd1cmVzL0ZpZ3VyZTRBX0Jlc3RfTW9kZWxfQWNjX0YxLnBuZyIsCiAgICAgICBkcGkgPSAzMDAsIGJnPSJ3aGl0ZSIpICMgYWRqdXN0IGRwaSBhY2NvcmRpbmdseQoKYGBgCgpGaWd1cmUgNEI6IFNlbnNpdGl2aXR5IEFuYWx5c2lzCgpgYGB7cn0KCiMgTGFiZWxzIGZvciBlYWNoIG1vZGVsIHN1YnNldAoKbGFiZWxzXyA9IGMoCiAgIndpbnRlcl9zYXIiID0gIk0xIiwgCiAgInN1bW1lcl9zYXIiID0gIk0yIiwKICAic3VtbWVyX3dpbnRlcl9zYXJfdGV4dCIgPSAiTTMiLAogICJzdW1tZXJfd2ludGVyX3NhciIgPSAiTTQiLAogICJhdXR1bW5fc3BlY3RyYWwiID0gIk01IiwKICAic3VtbWVyX3NwZWN0cmFsIiA9ICJNNiIsCiAgInN1bW1lcl9zcGVjdHJhbF9pbmQiID0gIk03IiwKICAic3BlY3RyYWxfc2FyX2luZCIgPSAiTTgiLAogICJzdW1tZXJfYXV0dW1uX3NwZWN0cmFsIiA9ICJNOSIsCiAgInNwZWN0cmFsX3NhciIgPSAiTTEwIiwKICAiZmluYWwiID0gIkZpbmFsIE1vZGVsIgopCgojIEFkZCBpbiB0aGUgZmluYWwgbW9kZWwgdG8gdGhlIHNlbnNpdGl2aXR5IGFuYWx5c2lzCgphZGQgPC0gYWNjbWVhcy5iZXN0ICU+JQogIHVuZ3JvdXAoKSAlPiUKICBzZWxlY3QobW9kZWwsZjEpICU+JQogIG11dGF0ZShzdWJzZXQgPSAiZmluYWwiKSAlPiUKICByZW5hbWUoZjFNYXggPSBmMSkKZ2xpbXBzZShhZGQpCmFjY21lYXMucyA8LSBhY2NtZWFzLnMgJT4lCiAgYmluZF9yb3dzKGFkZCkKcm0oYWRkKQoKcHJpbnQodW5pcXVlKGFjY21lYXMucyRzdWJzZXQpKQoKIyBHZW5lcmF0ZSB0aGUgYm94IHBsb3RzIG9mIEYxIHNjb3JlCgpmNGIgPC0gZ2dwbG90KGRhdGE9YWNjbWVhcy5zLCBhZXMoeD1yZW9yZGVyKHN1YnNldCxmMU1heCkseT1mMU1heCkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9bGFiZWxzXykgKwogIGxhYnMoeD0iSW5wdXQgRmVhdHVyZXMiLHk9Ik1heGltdW0gRjEgU2NvcmUiLCB0YWc9IkIiKSArCiAgdGhlbWVfYncoMTEpICsKICB0aGVtZSgKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLjIsMC4yLDAuMiwwLjIpLCAnbGluZXMnKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMSxmYWNlPSJpdGFsaWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMCwwLjQsMCwwKSwgImNtIikpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTExLGZhY2U9Iml0YWxpYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygwLjQsMCwwLDApLCAiY20iKSksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLAogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0PTEpLAogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkFyaWFsIikpCmY0YgoKIyBTYXZlIG91dAoKZ2dzYXZlKGY0YiwgZmlsZSA9ICIuLi8uLi9maWd1cmVzL0ZpZ3VyZTRCX01vZGVsX1NlbnNpdGl2aXR5LnBuZyIsCiAgICAgICBkcGkgPSAzMDAsIGJnPSJ3aGl0ZSIpICMgYWRqdXN0IGRwaSBhY2NvcmRpbmdseQpgYGAKCkNvbWJpbmUgdGhlIHR3byBmaWd1cmVzIGZvciBGaWd1cmUgNEFCOgoKYGBge3IgZmlnLndpZHRoPTcuNSwgZmlnLmhlaWdodD02fQoKZjQgPC0gZ2dhcnJhbmdlKGY0YSxmNGIsbnJvdz0yKQpmNAoKZ2dzYXZlKGY0LCBmaWxlID0gIi4uLy4uL2ZpZ3VyZXMvRmlndXJlNEFCX01vZGVsX0FjY3VyYWN5X1NlbnNpdGl2aXR5LnBuZyIsCiAgICAgICB3aWR0aD03LjUsIGhlaWdodD03LjUsIGRwaSA9IDMwMCwgYmc9IndoaXRlIikgIyBhZGp1c3QgZHBpIGFjY29yZGluZ2x5CgpgYGAKCiMjIEZpZ3VyZSA2OiBGZWF0dXJlIGltcG9ydGFuY2UgZnJvbSB0aGUgYmVzdCBtb2RlbAoKYGBge3J9CmdsaW1wc2UoZnRyX2ltcCkKYGBgCgpgYGB7ciBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0KCiMgIyBUaWR5IHRoZSBkYXRhIGZyYW1lCiMgZGYuaW1wIDwtIGZ0cl9pbXAgJT4lIAojICAgc2VsZWN0KC1jKC5nZW8sYHN5c3RlbTppbmRleGApKSAlPiUKIyAgIHJlbmFtZShtb2RlbCA9IHNlZWQpICU+JQojICAgbXV0YXRlKG1vZGVsID0gYXMuZmFjdG9yKG1vZGVsKSkgJT4lCiMgICAjIFN1bW1hcml6ZSBhY3Jvc3MgdG8gZ3JhYiB0aGUgcmVsYXRpdmUgaW1wb3J0YW5jZQojICAgcm93d2lzZSgpICU+JQojICAgbXV0YXRlKHRvdGFsID0gc3VtKGNfYWNyb3NzKEIxMV9hdXR1bW46VlZfd2ludGVyX2VudCkpKSAlPiUKIyAgIHVuZ3JvdXAoKSAlPiUKIyAgIG11dGF0ZShhY3Jvc3MoQjExX2F1dHVtbjpWVl93aW50ZXJfZW50LCB+IC4gKiAxMDAgLyB0b3RhbCkpICU+JQojICAgc2VsZWN0KC10b3RhbCkKIyBnbGltcHNlKGRmLmltcCkKCiMgVGlkeSB0aGUgZGF0YSBmcmFtZQpkZi5pbXAgPC0gZnRyX2ltcCAlPiUgCiAgc2VsZWN0KC1jKC5nZW8sYHN5c3RlbTppbmRleGApKSAlPiUKICByZW5hbWUobW9kZWwgPSBzZWVkKSAlPiUKICBtdXRhdGUobW9kZWwgPSBhcy5mYWN0b3IobW9kZWwpKSAlPiUKICAjIFN1bW1hcml6ZSBhY3Jvc3MgdG8gZ3JhYiB0aGUgcmVsYXRpdmUgaW1wb3J0YW5jZQogIGdyb3VwX2J5KG1vZGVsKSAlPiUKICBtdXRhdGUodG90YWwgPSBzdW0oYWNyb3NzKEIxMV9hdXR1bW46VlZfd2ludGVyX2VudCkpKSAlPiUKICBtdXRhdGUoYWNyb3NzKEIxMV9hdXR1bW46VlZfd2ludGVyX2VudCwgfiAuIC8gdG90YWwpKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgc2VsZWN0KC10b3RhbCkKCmBgYAoKYGBge3J9CgojIFBpdm90IGxvbmdlcgpkZi5pbXAucCA8LSBkZi5pbXAgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAtbW9kZWwpICU+JQogIHJlbmFtZShpbXBvcnRhbmNlID0gdmFsdWUsCiAgICAgICAgIGJhbmQgPSBuYW1lKSAlPiUKICBtdXRhdGUoc2Vhc29uID0gaWZfZWxzZShzdHJfZGV0ZWN0KGJhbmQsIl9hdXR1bW4iKSwgIkF1dHVtbiBTcGVjdHJhbCIsICJTdW1tZXIgU3BlY3RyYWwiKSwKICAgICAgICAgc2Vhc29uID0gaWZfZWxzZShzdHJfZGV0ZWN0KGJhbmQsIlZWX3dpbnRlciIpLCAiV2ludGVyIFNBUiIsIHNlYXNvbiksCiAgICAgICAgIHNlYXNvbiA9IGlmX2Vsc2Uoc3RyX2RldGVjdChiYW5kLCJWSF93aW50ZXIiKSwgIldpbnRlciBTQVIiLCBzZWFzb24pLAogICAgICAgICBzZWFzb24gPSBpZl9lbHNlKHN0cl9kZXRlY3QoYmFuZCwiVlZfc3VtbWVyIiksICJTdW1tZXIgU0FSIiwgc2Vhc29uKSwKICAgICAgICAgc2Vhc29uID0gaWZfZWxzZShzdHJfZGV0ZWN0KGJhbmQsIlZIX3N1bW1lciIpLCAiU3VtbWVyIFNBUiIsIHNlYXNvbikpCmdsaW1wc2UoZGYuaW1wLnApCgpgYGAKCmBgYHtyIG1lc3NhZ2U9Rn0KCiMgR3JhYiB0aGUgdG9wIDIwIG92ZXIgYWxsIG1vZGVsIHJ1bnMKCnRvcCA8LSBkZi5pbXAucCAlPiUKICBncm91cF9ieShiYW5kKSAlPiUKICBzdW1tYXJpemUobWVkaWFuID0gbWVkaWFuKGltcG9ydGFuY2UpKSAlPiUKICB1bmdyb3VwKCkKCnRvcCA8LSBoZWFkKGFycmFuZ2UodG9wLGRlc2MobWVkaWFuKSksIG4gPSAyMCkKCiMgQ29sb3IgcGFsZXR0ZQoKY29scyA8LSBjKAogICJTdW1tZXIgU3BlY3RyYWwiID0gIiM4N0NFRUIiLCAKICAiQXV0dW1uIFNwZWN0cmFsIiA9ICIjREFBNTIwIiwKICAiV2ludGVyIFNBUiIgPSAiZ3JheTI5IiwKICAiU3VtbWVyIFNBUiIgPSAiZ3JheTg5IgopCgojIEJveHBsb3QKCiMgJT4lIGZpbHRlcihiYW5kICVpbiUgdG9wJGJhbmQpCmY2IDwtIGdncGxvdChkYXRhPWRmLmltcC5wICU+JSBmaWx0ZXIoYmFuZCAlaW4lIHRvcCRiYW5kKSwgCiAgICAgICAgICAgICAgYWVzKHg9cmVvcmRlcihiYW5kLGltcG9ydGFuY2UpLCBmaWxsPXNlYXNvbikpICsKICBnZW9tX2JveHBsb3QoYWVzKHk9aW1wb3J0YW5jZSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC41KSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbHMsIAogICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkF1dHVtbiBTcGVjdHJhbCIsIlN1bW1lciBTQVIiLCJTdW1tZXIgU3BlY3RyYWwiLCJXaW50ZXIgU0FSIikpICsKICBjb29yZF9mbGlwKCkgKwogIHRoZW1lX2J3KDExKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMSksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCB2anVzdD0wLCBzaXplPTExKSwKICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTEsZmFjZT0iaXRhbGljIiksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDEuMiwwLjUpLCAjIExlZnQtYWxpZ25zIHRoZSBsZWdlbmRzCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMSksCiAgICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiQXJpYWwiKSwKICAgICAgICBwbG90Lm1hcmdpbj11bml0KGMoMC41LDAuNSwwLjUsMC41KSwiY20iKSkgKwogIGxhYnMoeD0iRmVhdHVyZSIsIHk9IkltcG9ydGFuY2UiLCBmaWxsPSJTZWFzb246ICIpCmY2CgpnZ3NhdmUoZjYsIGZpbGUgPSAiLi4vLi4vZmlndXJlcy9GaWd1cmU2X0ZlYXR1cmVJbXBvcnRhbmNlLnBuZyIsCiAgICAgICBkcGk9MzAwLCBiZz0id2hpdGUiKSAjIGFkanVzdCBkcGkgYWNjb3JkaW5nbHkKCmBgYAoKQ2xlYW4gdXAhCgpgYGB7cn0Kcm0obGlzdCA9IGxzLnN0cihtb2RlID0gJ251bWVyaWMnKSkKcm0oYWNjbWVhcyxhY2NtZWFzLmJlc3QsYWNjbWVhcy5tbixhY2NtZWFzLnMsZGYuaW1wLAogICBkZi5pbXAucCxmNCxmNGEsZjRiLGY2LGZ0cl9pbXAsdG9wKQpnYygpCmBgYAoKIyMgRmlndXJlcyA3LCA4IC0gQ2FzZSBTdHVkeTogTGFuZHNjYXBlIFBhdGNoIER5bmFtaWNzCgojIEZpZ3VyZSA3OiBTcGF0aWFsIEFncmVlbWVudAoKYGBge3J9CgpicmV3ZXIucGFsKG49NSwiU2V0MSIpCgpjb2xzIDwtIGMoIiM0REFGNEEiLCAiIzk4NEVBMyIsICIjRkY3RjAwIikKCmdsaW1wc2UocmVmLmdsb2JhbCkKCiMgR2V0IGFuIGF2ZXJhZ2UgZjEgc2NvcmUgdGFibGUKZjFtbiA8LSByZWYuZ2xvYmFsICU+JQogIGdyb3VwX2J5CgojIEFkZCBhIHN0YXRpc3RpY3MgY29sdW1uIGZvciBsZWdlbmQgKGNvdWxkIGRvIHRoaXMgZm9yIEYxIHRvbyAuLi4pCnJlZi5nbG9iYWwubSA8LSByZXNoYXBlMjo6bWVsdCgKICByZWYuZ2xvYmFsLCBpZC52YXJzID0gYygiYmxvY2tzaXplIiwgInNvdXJjZSIsICJyZWdpb24iKSwgCiAgbWVhc3VyZS52YXJzID0gYygicHJlYyIsICJyZWMiKSwgdmFyaWFibGUubmFtZSA9ICJzdGF0aXN0aWMiCikKCmdsaW1wc2UocmVmLmdsb2JhbC5tKQoKZjdhIDwtIGdncGxvdChkYXRhPXJlZi5nbG9iYWwubSkgKwogIGdlb21fbGluZShhZXMoeD1ibG9ja3NpemUseT12YWx1ZSxjb2xvcj1mYWN0b3Ioc291cmNlKSwgbGluZXR5cGU9c3RhdGlzdGljKSwgbGluZXdpZHRoPTAuNikgKwogIGdlb21fcG9pbnQoZGF0YT1yZWYuZ2xvYmFsLCBhZXMoeD1ibG9ja3NpemUsIHk9ZjEsIGNvbG9yPXNvdXJjZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPWMoMSwzLDUsNyw5KSkgKwogIHNjYWxlX2xpbmV0eXBlX21hbnVhbCh2YWx1ZXMgPSBjKCJwcmVjIiA9ICJkb3R0ZWQiLCAicmVjIiA9ICJzb2xpZCIpLCBuYW1lPSJTdGF0aXN0aWM6ICIsCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscz1jKCJQcmVjaXNpb24iLCJSZWNhbGwiKSkgKwogIGZhY2V0X3dyYXAofnJlZ2lvbiwgc2NhbGVzID0gImZpeGVkIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9Y29scywgbGFiZWxzPWMoIkxBTkRGSVJFIEVWVCIsIlVTRlMgVHJlZU1hcCIsIlVTRlMgSVRTUCIpLCBuYW1lPSJTb3VyY2U6ICIpICsKICB0aGVtZV9saWdodCgxNCkgKwogIHlsaW0oMCwxKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICAgICAgbGVnZW5kLmJveCA9ICJ2ZXJ0aWNhbCIsCiAgICAgICAgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAuNSwwLjUpLCAjIExlZnQtYWxpZ25zIHRoZSBsZWdlbmRzCiAgICAgICAgbGVnZW5kLnNwYWNpbmcueSA9IHVuaXQoLTEwLCAicHQiKSwgIyBBZGp1c3RzIHRoZSBnYXAgYmV0d2VlbiB0aGUgbGVnZW5kcwogICAgICAgIGxlZ2VuZC50ZXh0ID0gZ2d0ZXh0OjplbGVtZW50X21hcmtkb3duKGhhbGlnbiA9IDApLCAjIFRoaXMgYWxpZ25zIGVhY2ggaW5kaXZpZHVhbCBsZWdlbmQncyB0ZXh0IHRvIHRoZSBsZWZ0CiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyLGZhY2U9Iml0YWxpYyIpLAogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkFyaWFsIikpICsKICBsYWJzKHg9IkJsb2Nrc2l6ZSAocGl4ZWxzKSIseT0iVmFsdWUiKQogIApmN2EKCmdnc2F2ZShmN2EsIGZpbGUgPSAiLi4vLi4vZmlndXJlcy9GaWd1cmU3X0dsb2JhbF9QcmVjUmVjX0FncmVlbWVudC5wbmciLCBkcGk9MzAwKQoKYGBgCgpGb2NhbCBhY2N1cmFjeToKCmBgYHtyIG1lc3NhZ2U9Rn0KCiMgcmVmLmZvY2FsJHJlZmJ1ZGVucyA8LSBsb2coMSArIHJlZi5mb2NhbCR0cCArIHJlZi5mb2NhbCRmbikKIyAKIyBnZ3Bsb3QocmVmLmZvY2FsICU+JSBmaWx0ZXIocmVnaW9uPT0iU1JNRSIpLCBhZXMoeCA9IHByZWMsIHkgPSByZWMsIGNvbG9yID0gcmVmYnVkZW5zKSkgKwojICAgIGdlb21fcG9pbnQoc2l6ZSA9IDIsIGFscGhhID0gMC45KSArCiMgICAgc2NhbGVfY29sb3JfdmlyaWRpc19jKCkgKwojICAgIGZhY2V0X2dyaWQocm93cyA9IHZhcnMoZ2VvZ19zY2FsZSksIGNvbHMgPSB2YXJzKGJsb2Nrc2l6ZSksIHNjYWxlcyA9ICJmaXhlZCIpICsKIyAgICB0aGVtZV9saWdodCgpICsKIyAgICBsYWJzKAojICAgICAgIHRpdGxlID0gJ1NwYXRpYWxseSBleHBsaWNpdCBhY2N1cmFjeTogUHJlY2lzaW9uICh4KSB2cy4gUmVjYWxsICh5KScsCiMgICAgICAgc3VidGl0bGUgPSAnZm9yIG11bHRpcGxlIGFuYWx5dGljYWwgdW5pdHMgYW5kIHNwYXRpYWwgc3VwcG9ydCBsZXZlbHMnLAojICAgICAgIGNvbG9yID0gJ3JlZmJ1ZGVucycsCiMgICAgICAgeCA9ICdQcmVjaXNpb24nLAojICAgICAgIHkgPSAnUmVjYWxsJwojICAgICkgKwojICAgIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLCAxKSwgeWxpbSA9IGMoMCwgMSkpICsKIyAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKCmBgYAoKSm9pbiB0aGUgdHdvIHBsb3RzOgoKYGBge3J9CiMgZjcgPC0gZ2dhcnJhbmdlKGdsb2JhbF9wcmVjcmVjLGZvY2FsLnByZWMsZm9jYWwucmVjLG5yb3c9MSxsYWJlbHM9YygiQSIsIkIiLCJDIikpCiMgZjcKIyBnZ3NhdmUoZjcsIGZpbGU9Ii4uLy4uL2ZpZ3VyZXMvRmlndXJlN19HbG9iYWxfRm9jYWxfQWdyZWVtZW50LnBuZyIsIGRwaT0zMDApCmBgYAoKQ2xlYW4gdXAhIAoKYGBge3J9CnJtKHJlZi5nbG9iYWwscmVmLmdsb2JhbC5tLGY3YSxmN2IsZjcscmVmLmZvY2FsKQpnYygpCmBgYAoKIyBGaWd1cmUgODogTGFuZHNjYXBlIFBhdGNoIER5bmFtaWNzCgpgYGB7cn0KdW5pcXVlKGZhY3RvcihwYXRjaF9tZXRyaWNzJHNvdXJjZSkpCnN1bW1hcnkocGF0Y2hfbWV0cmljcykKYGBgCgpDYWxjdWxhdGUgc29tZSBncm91cGVkIHN0YXRpc3RpY3MgKHRvIGNvbXBhcmUgd2l0aCB0aGUgY2xhc3MgbWV0cmljcyByZXN1bHRzKQoKYGBge3IgbWVzc2FnZT1GLCB3YXJuaW5nPUYsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTh9CgojIEFsc28gY3JlYXRlIGEgZ3JvdXBlZCBzdW1tYXJ5CihwYXRjaC5zdW1tYXJ5IDwtIHBhdGNoX21ldHJpY3MgJT4lCiAgZ3JvdXBfYnkoc291cmNlLHJlZ2lvbikgJT4lCiAgc3VtbWFyaXplKGFyZWFfbWQgPSBtZWRpYW4oYXJlYSksICMgY29udmVydCB0byBoZWN0YXJlcwogICAgICAgICAgICBhcmVhX21uID0gbWVhbihhcmVhKSwKICAgICAgICAgICAgYXJlYV9zdW0gPSBzdW0oYXJlYSksCiAgICAgICAgICAgIHBlcmltX21kID0gbWVkaWFuKHBlcmltZXRlciksCiAgICAgICAgICAgIHBlcmltX21uID0gbWVhbihwZXJpbWV0ZXIpLAogICAgICAgICAgICBwYXJfbWQgPSBtZWRpYW4ocGVyaW1ldGVyX2FyZWFfcmF0aW8pLAogICAgICAgICAgICBwYXJfbW4gPSBtZWFuKHBlcmltZXRlcl9hcmVhX3JhdGlvKSwKICAgICAgICAgICAgc2lfbWQgPSBtZWRpYW4oc2hhcGVfaW5kZXgpLAogICAgICAgICAgICBzaV9tbiA9IG1lYW4oc2hhcGVfaW5kZXgpKSAlPiUKICB1bmdyb3VwKCkpCgoocGF0Y2gubG9uZyA8LSBwYXRjaC5zdW1tYXJ5ICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhjb250YWlucygiXyIpKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAibWV0cmljIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIikpCgpwYXRjaC5sb25nJHNvdXJjZSA8LSBmYWN0b3IocGF0Y2gubG9uZyRzb3VyY2UsbGV2ZWxzPWMoJ0FzcGVuMTBtJywgJ0FzcGVuMzBtJywgJ0xGRVZUJywgJ1RyZWVNYXAnLCAnSVRTUCcpKQoKKGdncGxvdChkYXRhID0gcGF0Y2gubG9uZywgYWVzKHg9c291cmNlLCB5PXZhbHVlLCBmaWxsPXJlZ2lvbikpICsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb249ImRvZGdlIiwgd2lkdGg9MC43KSArCiAgICBmYWNldF93cmFwKH5tZXRyaWMsIHNjYWxlcz0iZnJlZSIpICsgCiAgICB0aGVtZV9taW5pbWFsKDE0KSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChmYW1pbHkgPSAiQXJpYWwiKSkpCgooZjhzIDwtIGdncGxvdChkYXRhID0gcGF0Y2gubG9uZywgYWVzKHg9c291cmNlLCB5PXZhbHVlLCBmaWxsPXJlZ2lvbikpICsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb249ImRvZGdlIiwgd2lkdGg9MC43KSArIAogICAgdGhlbWVfbWluaW1hbCgxNCkgKwogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgIHRleHQgPSBlbGVtZW50X3RleHQoZmFtaWx5ID0gIkFyaWFsIikpKQoKYGBgCgpHcmFiIHNvbWUgc3RhdGlzdGljcyBvbiB0aGUgcGF0Y2ggc2l6ZToKCmBgYHtyfQooYSA8LSBwYXRjaC5sb25nICU+JSBmaWx0ZXIobWV0cmljPT0iYXJlYV9tbiIsc291cmNlPT0iQXNwZW4xMG0iKSkKKGIgPC0gcGF0Y2gubG9uZyAlPiUgZmlsdGVyKG1ldHJpYz09ImFyZWFfbW4iLHNvdXJjZT09IkxGRVZUIikpCgooYyA8LSBwYXRjaC5sb25nICU+JSBmaWx0ZXIobWV0cmljPT0iYXJlYV9tZCIsc291cmNlPT0iQXNwZW4xMG0iKSkKKGQgPC0gcGF0Y2gubG9uZyAlPiUgZmlsdGVyKG1ldHJpYz09ImFyZWFfbWQiLHNvdXJjZT09IkxGRVZUIikpCgpwcmludCgiTWVhbiBhbmQgbWVkaWFuIHBhdGNoIHNpemVzOiAiKQpwYXN0ZTAoIkFzcGVuMTBtIG1lYW46ICIsYSR2YWx1ZSkKcGFzdGUwKCJMRkVWVCBtZWFuOiAiLGIkdmFsdWUpCnBhc3RlMCgiQXNwZW4xMG0gbWVkaWFuOiAiLGMkdmFsdWUpCnBhc3RlMCgiTEZFVlQgbWVhbjogIixkJHZhbHVlKQoKcHJpbnQoIkRpZmZlcmVuY2UgaW4gbWVhbiBhcmVhOiAiKQooKGIkdmFsdWUtYSR2YWx1ZSkvYiR2YWx1ZSkqMTAwCgpwcmludCgiRGlmZmVyZW5jZSBpbiBtZWRpYW4gYXJlYTogIikKKChkJHZhbHVlLWMkdmFsdWUpL2QkdmFsdWUpKjEwMAoKcHJpbnQoIk1lYW4gUGVyaW1ldGVyIGFyZWEgcmF0aW86ICIpCihhIDwtIHBhdGNoLmxvbmcgJT4lIGZpbHRlcihtZXRyaWM9PSJwYXJfbW4iLHNvdXJjZT09IkFzcGVuMTBtIikpCihiIDwtIHBhdGNoLmxvbmcgJT4lIGZpbHRlcihtZXRyaWM9PSJwYXJfbW4iLHNvdXJjZT09IkxGRVZUIikpCgpwcmludCgiRGlmZmVyZW5jZSBpbiBQQVI6ICIpCigoYiR2YWx1ZS1hJHZhbHVlKS9iJHZhbHVlKSoxMDAKCnJtKGEsYixjLGQpCmBgYAoKQm94cGxvdCBhcyBmYWNldCB3cmFwIGZvciBwYXRjaCBtZXRyaWNzOgoKYGBge3IgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9MTB9CgpicmV3ZXIucGFsKG49NSwiU2V0MSIpCgpjb2xzIDwtIGMoIiMwMDVhMzIiLCIjYTFkOTliIikKCihkZiA8LSBwYXRjaF9tZXRyaWNzICU+JQogICMgbXV0YXRlKGFyZWFfaGEgPSBhcmVhKjEwMCkgJT4lCiAgc2VsZWN0KC1jKFgsaW5kZXgsc2hhcGVfaW5kZXgpKSAlPiUKICBwaXZvdF9sb25nZXIoY29udGFpbnMoYygiYXJlYSIsInBlcmltZXRlcl9hcmVhX3JhdGlvIikpKSAlPiUKICBhcnJhbmdlKHNvdXJjZSwgZGVzYyh2YWx1ZSkpICU+JQogIG11dGF0ZShuYW1lID0gYXMuY2hhcmFjdGVyKG5hbWUpLAogICAgICAgICBuYW1lID0gcmVjb2RlKG5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgImFyZWEiID0gIlBhdGNoIFNpemUgKGhhKSIsCiAgICAgICAgICAgICAgICAgICAgICAgInBlcmltZXRlcl9hcmVhX3JhdGlvIiA9ICJQZXJpbWV0ZXIvQXJlYSBSYXRpbyIpKSkKCmRmJHNvdXJjZSA8LSBmYWN0b3IoZGYkc291cmNlLAogICAgICAgICAgICAgICAgICAgIGxldmVscz1jKCdBc3BlbjEwbScsICdBc3BlbjMwbScsICdMRkVWVCcsICdUcmVlTWFwJywgJ0lUU1AnKSkKIAooZjhhIDwtIGdncGxvdChkYXRhPWRmLCBhZXMoeSA9IHZhbHVlLCB4ID0gZmFjdG9yKHNvdXJjZSksIGZpbGwgPSBmYWN0b3IocmVnaW9uKSkpICsKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaXplID0gMC4yKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zPSJsb2cxMCIsbGFiZWxzPWxhYmVsX251bWJlcl9zaShhY2N1cmFjeSA9IDEpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNvbHMpICsKICBmYWNldF93cmFwKH5uYW1lLCBzY2FsZXMgPSAiZnJlZV95IiwgbnJvdz0xKSArCiAgbGFicyh4PSJcbkRhdGEgU291cmNlIix5PSJWYWx1ZSIsdGl0bGU9IlBhdGNoIE1ldHJpY3MiLCBmaWxsPSJSZWdpb246ICIpICsKICB0aGVtZV9saWdodCgxMikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZT0xMSksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCB2anVzdD0wLjEsIHNpemU9MTEpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBmYWNlPSJpdGFsaWMiLCB2anVzdD0xKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZT0xMiwgZmFjZT0iaXRhbGljIiwgdmp1c3Q9LTEpLAogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKDAuNSwwLjUsMC41LDAuNSksImNtIiksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJ0b3AiLAogICAgICAgIGxlZ2VuZC5zcGFjaW5nLnggPSB1bml0KDAuNSwiY20iKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJBcmlhbCIpKSkKCmdnc2F2ZShmOGEsIGZpbGUgPSAiLi4vLi4vZmlndXJlcy9GaWd1cmU4QV9wYXRjaF9tZXRyaWNzLnBuZyIsIGRwaSA9IDMwMCkgIyBhZGp1c3QgZHBpIGFjY29yZGluZ2x5CgpgYGAKClBsb3QgY2xhc3MgbWV0cmljcyBhcyBmYWNldCB3cmFwOgoKYGBge3IgZmlnLmhlaWdodD01LCBmaWcud2lkdGg9MTAsIG1lc3NhZ2U9Rn0KCiMgQ2FsY3VsYXRlIGFyZWEgaW4gc3F1YXJlIG1ldGVycwpzcm1lX2FyZWFfa20yIDwtIHN0X2FyZWEoc3JtZSkgLyAxZTYKd3JuZl9hcmVhX2ttMiA8LSBzdF9hcmVhKHdybmYpIC8gMWU2CgooZGYgPC0gY2xhc3NfbWV0cmljcyAlPiUKICBtdXRhdGUodG90YWxfYXJlYSA9IHRvdGFsX2FyZWEqMC4wMSwKICAgICAgICAgcHJvcF9hcmVhID0gaWZfZWxzZShyZWdpb249PSJTUk1FIiwgYXMuZG91YmxlKCh0b3RhbF9hcmVhL3NybWVfYXJlYV9rbTIqMTAwKSksIDAuMCksCiAgICAgICAgIHByb3BfYXJlYSA9IGlmX2Vsc2UocmVnaW9uPT0iV1JORiIsIGFzLmRvdWJsZSgodG90YWxfYXJlYS93cm5mX2FyZWFfa20yKjEwMCkpLCBwcm9wX2FyZWEpKSAlPiUKICBzZWxlY3QoLWMoWCkpICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYyhjb250YWlucygiXyIpKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAibWV0cmljIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIikgJT4lCiAgbXV0YXRlKG1ldHJpYyA9IGFzLmNoYXJhY3RlcihtZXRyaWMpLAogICAgICAgICBtZXRyaWMgPSByZWNvZGUobWV0cmljLAogICAgICAgICAgICAgICAgICAgICAgICAgIm5fcGF0Y2giID0gIk51bWJlciBvZiBQYXRjaGVzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJwYXRjaF9kZW4iID0gIlBhdGNoIERlbnNpdHkiLAogICAgICAgICAgICAgICAgICAgICAgICAgInRvdGFsX2FyZWEiID0gIlRvdGFsIGFyZWEgKGttMikiLAogICAgICAgICAgICAgICAgICAgICAgICAgInByb3BfYXJlYSIgPSAiUHJvcG9ydGlvbiBvZiBBcmVhIikpKQoKZGYkc291cmNlIDwtIGZhY3RvcihkZiRzb3VyY2UsIGxldmVscz1jKCdBc3BlbjEwbScsICdBc3BlbjMwbScsICdMRkVWVCcsICdUcmVlTWFwJywgJ0lUU1AnKSkKaGVhZChkZikKCihmOGIgPC0gZ2dwbG90KGRhdGE9ZGYsIGFlcyh5PXZhbHVlLCB4PWZhY3Rvcihzb3VyY2UpLCBmaWxsPWZhY3RvcihyZWdpb24pKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb249ImRvZGdlIiwgd2lkdGg9MC43KSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OmxhYmVsX251bWJlcl9zaShhY2N1cmFjeSA9IDEpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWNvbHMpICsKICBsYWJzKHg9IiIsIHk9IlZhbHVlIiwgdGl0bGU9IkxhbmRzY2FwZSBNZXRyaWNzIiwgZmlsbD0iUmVnaW9uOiAiKSArCiAgdGhlbWUoYXhpcy50aXRsZS54ID0gTlVMTCkgKwogIGZhY2V0X3dyYXAofm1ldHJpYywgc2NhbGVzID0gImZyZWVfeSIpICsKICB0aGVtZV9saWdodCgxMikgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSwgc2l6ZT0xMSksCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCB2anVzdD0wLjEsIHNpemU9MTEpLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBmYWNlPSJpdGFsaWMiLCB2anVzdD0wLjUpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTEyLCBmYWNlPSJpdGFsaWMiLCB2anVzdD0tMC41KSwKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYygwLjUsMC41LDAuNSwwLjUpLCJjbSIpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgIGxlZ2VuZC5zcGFjaW5nLnggPSB1bml0KDAuNSwiY20iKSwKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGZhbWlseSA9ICJBcmlhbCIpKSkKCmdnc2F2ZShmOGIsIGZpbGUgPSAiLi4vLi4vZmlndXJlcy9GaWd1cmU4Ql9sYW5kc2NhcGVfbWV0cmljcy5wbmciLCBkcGkgPSAzMDApICMgYWRqdXN0IGRwaSBhY2NvcmRpbmdseQoKYGBgCgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTB9CihhcnIgPC0gZ2dhcnJhbmdlKGY4YixmOGEsbnJvdz0yLG5jb2w9MSxsYWJlbHM9YygiQSIsIkIiKSwgY29tbW9uLmxlZ2VuZCA9IFQpKQpnZ3NhdmUoYXJyLCBmaWxlPSIuLi8uLi9maWd1cmVzL0ZpZ3VyZThfTGFuZHNjYXBlX1BhdGNoX01ldHJpY3MucG5nIiwgZHBpPTMwMCkKYGBgCgpUaGUgMTAtbSBhc3BlbiBjbGFzc2lmaWNhdGlvbiBpZGVudGlmaWVkIFh4IG1vcmUgcGF0Y2ggdGhhbiByZWZlcmVuY2UgaW1hZ2VzOgoKYGBge3J9CgpwcmludCgiJSBEaWZmZXJlbmNlIGluIG51bWJlciBvZiBwYXRjaGVzOiAiKQphIDwtIGRmICU+JSBmaWx0ZXIobWV0cmljPT0iTnVtYmVyIG9mIFBhdGNoZXMiLHNvdXJjZT09IkFzcGVuMTBtIikKYiA8LSBkZiAlPiUgZmlsdGVyKG1ldHJpYz09Ik51bWJlciBvZiBQYXRjaGVzIixzb3VyY2U9PSJMRkVWVCIpCigoYiR2YWx1ZS1hJHZhbHVlKS9iJHZhbHVlKSoxMDAKCnByaW50KCIlIERpZmZlcmVuY2UgaW4gcGF0Y2ggZGVuc2l0eTogIikKYSA8LSBkZiAlPiUgZmlsdGVyKG1ldHJpYz09IlBhdGNoIERlbnNpdHkiLHNvdXJjZT09IkFzcGVuMTBtIikKYiA8LSBkZiAlPiUgZmlsdGVyKG1ldHJpYz09IlBhdGNoIERlbnNpdHkiLHNvdXJjZT09IkxGRVZUIikKKChiJHZhbHVlLWEkdmFsdWUpL2IkdmFsdWUpKjEwMAoKcHJpbnQoIiUgRGlmZmVyZW5jZSBpbiB0b3RhbCBhcmVhOiIpCmEgPC0gZGYgJT4lIGZpbHRlcihtZXRyaWM9PSJUb3RhbCBhcmVhIChrbTIpIixzb3VyY2U9PSJBc3BlbjEwbSIpCmFhIDwtIGRmICU+JSBmaWx0ZXIobWV0cmljPT0iVG90YWwgYXJlYSAoa20yKSIsc291cmNlPT0iQXNwZW4zMG0iKQpiIDwtIGRmICU+JSBmaWx0ZXIobWV0cmljPT0iVG90YWwgYXJlYSAoa20yKSIsc291cmNlPT0iTEZFVlQiKQooKGIkdmFsdWUtYSR2YWx1ZSkvYiR2YWx1ZSkqMTAwCigoYiR2YWx1ZS1hYSR2YWx1ZSkvYiR2YWx1ZSkqMTAwCgpybShhLGFhLGIpCgpgYGAKCgojIFN1cHBsZW1lbnRhbAoKRmlndXJlIFMxOiBQaGVub2xvZ3kgYWNyb3NzIHRoZSBTUk1FIHN0dWR5IHJlZ2lvbgoKYGBge3J9CgojIFNwYXRpYWwgbWFwKHMpIG9mIGtleSBwaGVub2xvZ2ljYWwgbWV0cmljcwoKYnJlYWtzX2RhdGVzIDwtIGFzLkRhdGUoYygiMjAyMC0wMS0wMSIsICIyMDIxLTAxLTAxIiwgIjIwMjItMDEtMDEiKSkKYnJlYWtzX251bWVyaWMgPC0gYXMubnVtZXJpYyhicmVha3NfZGF0ZXMpICAjIENvbnZlcnQgdG8gbnVtZXJpYyAoZGF5cyBzaW5jZSAxOTcwLTAxLTAxLCBieSBkZWZhdWx0KQpsYWJlbHNfZGF0ZXMgPC0gZm9ybWF0KGJyZWFrc19kYXRlcywgIiVZLSVtLSVkIikKCnAxIDwtIGdncGxvdChkYXRhPWJsb2NrcykgKwogIGdlb21fc2YoYWVzKGZpbGw9TWF0dXJpdHlfMSkpICsKICBzY2FsZV9maWxsX2NvbnRpbnVvdXMobG93ID0gImxpZ2h0Z3JlZW4iLCBoaWdoID0gImRhcmtncmVlbiIsCiAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGZ1bmN0aW9uKHgpIGZvcm1hdChhcy5EYXRlKGFzLm51bWVyaWMoeCksIG9yaWdpbj0iMTk3MC0wMS0wMSIpLCAiJUIgJWQiKSkgKwogIGdlb21fc2YoZGF0YT1zcm1lLGZpbGw9TkEsY29sb3I9ImJsYWNrIixzaXplPTIuNSkgKwogIGxhYnMoZmlsbD0iTWF0dXJpdHkiKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9jb2xvdXJiYXIoYmFyd2lkdGggPSAwLjUsIGJhcmhlaWdodCA9IDUuNSwgdGlja3M9RiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwucG9zaXRpb24gPSAicmlnaHQiLCB0aXRsZS5wb3NpdGlvbiA9ICJ0b3AiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbC50aGVtZSA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDAsIHNpemUgPSA4KSkpICsKICB0aGVtZV92b2lkKCkKCnAyIDwtIGdncGxvdChkYXRhPWJsb2NrcykgKwogIGdlb21fc2YoYWVzKGZpbGw9RG9ybWFuY3lfMSkpICsKICBzY2FsZV9maWxsX2NvbnRpbnVvdXMobG93ID0gIiNmZmZmZDQiLCBoaWdoID0gIiM5OTM0MDQiLAogICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBmdW5jdGlvbih4KSBmb3JtYXQoYXMuRGF0ZShhcy5udW1lcmljKHgpLCBvcmlnaW49IjE5NzAtMDEtMDEiKSwgIiVCICVkIikpICsKICBnZW9tX3NmKGRhdGE9c3JtZSxmaWxsPU5BLGNvbG9yPSJibGFjayIsc2l6ZT0yLjUpICsKICBsYWJzKGZpbGw9IkRvcm1hbmN5IikgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3VyYmFyKGJhcndpZHRoID0gMC41LCBiYXJoZWlnaHQgPSA1LjUsIHRpY2tzPUYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsLnBvc2l0aW9uID0gInJpZ2h0IiwgdGl0bGUucG9zaXRpb24gPSAidG9wIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFiZWwudGhlbWUgPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCBzaXplID0gOCkpKSArCiAgdGhlbWVfdm9pZCgpCgpnZ2FycmFuZ2UocDEscDIpCgojICMgQWRkIGEgc3RhdGlzdGljcyBjb2x1bW4gZm9yIGxlZ2VuZCAoY291bGQgZG8gdGhpcyBmb3IgRjEgdG9vIC4uLikKIyBibG9ja3MubSA8LSByZXNoYXBlMjo6bWVsdCgKIyAgIGJsb2NrcywgaWQudmFycyA9IGMoImlkIiwiZWxldmF0aW9uX21uIiksIAojICAgbWVhc3VyZS52YXJzID0gYygiR3JlZW51cF8xIiwiTWlkR3JlZW51cF8xIiwiTWF0dXJpdHlfMSIsIlBlYWtfMSIsCiMgICAgICAgICAgICAgICAgICAgICJNaWRHcmVlbmRvd25fMSIsIlNlbmVzY2VuY2VfMSIsIkRvcm1hbmN5XzEiKSwgdmFyaWFibGUubmFtZSA9ICJtZXRyaWMiCiMgKQoKIyBBZGQgYSBzdGF0aXN0aWNzIGNvbHVtbiBmb3IgbGVnZW5kIChjb3VsZCBkbyB0aGlzIGZvciBGMSB0b28gLi4uKQpibG9ja3MubSA8LSByZXNoYXBlMjo6bWVsdCgKICBibG9ja3MsIGlkLnZhcnMgPSBjKCJpZCIsImVsZXZhdGlvbl9tbiIpLCAKICBtZWFzdXJlLnZhcnMgPSBjKCJHcmVlbnVwXzEiLCJNYXR1cml0eV8xIiwiUGVha18xIiwiRG9ybWFuY3lfMSIpLCB2YXJpYWJsZS5uYW1lID0gIm1ldHJpYyIKKSAlPiUKICBtdXRhdGUobWV0cmljID0gYXMuY2hhcmFjdGVyKG1ldHJpYyksCiAgICAgICAgIG1ldHJpYyA9IGFzLmZhY3RvcihyZWNvZGUobWV0cmljLAogICAgICAgICAgICAgICAgICAgICAgICAgIkdyZWVudXBfMSIgPSAiR3JlZW51cCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiTWF0dXJpdHlfMSIgPSAiTWF0dXJpdHkiLAogICAgICAgICAgICAgICAgICAgICAgICAgIlBlYWtfMSIgPSAiUGVhayBHcmVlbm5lc3MiLAogICAgICAgICAgICAgICAgICAgICAgICAgIkRvcm1hbmN5XzEiID0gIkRvcm1hbmN5IikpKQogIApibG9ja3MubSRtZXRyaWMgPC0gZmFjdG9yKGJsb2Nrcy5tJG1ldHJpYywgbGV2ZWxzPWMoJ0dyZWVudXAnLCAnTWF0dXJpdHknLCAnUGVhayBHcmVlbm5lc3MnLCAnRG9ybWFuY3knKSkKCmhlYWQoYmxvY2tzLm0pCgojIERvdCBwbG90IG9mIHBoZW5vbG9neSBtZXRyaWMgYnkgZWxldmF0aW9uIGZvciBhbGwgYmxvY2tzCgoocDUgPC0gZ2dwbG90KGRhdGE9YmxvY2tzLm0sIGFlcyh4PXZhbHVlLHk9ZWxldmF0aW9uX21uKSkgKwogIGdlb21fc21vb3RoKG1ldGhvZD0ibG0iLGNvbG91cj0iZ3JheTQwIiwgZmlsbD0iZ3JheTcwIiwgc2l6ZT0wLjgpICsKICBnZW9tX3BvaW50KHNpemU9MS4yKSArCiAgZmFjZXRfd3JhcCh+bWV0cmljLCBzY2FsZXM9ImZyZWVfeCIpICsKICB0aGVtZV9saWdodCgxMikgKwogICAgbGFicyh4PSJEYXRlIix5PSJFbGV2YXRpb24iKSkKCihwNiA8LSBnZ3Bsb3QoZGF0YT1ibG9ja3MubSwgYWVzKHg9dmFsdWUseT1lbGV2YXRpb25fbW4sY29sb3I9bWV0cmljKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0xLjIpICsKICB0aGVtZV9saWdodCgxMikpCgpgYGAKCgpST0MsIEYxLCBNQ0M6CgpgYGB7cn0KCmFjY21lYXMgPC0gcmVhZF9jc3YoJy4uLy4uL2RhdGEvdGFidWxhci9tb2QvcmVzdWx0cy9hY2NtZWFzX3Byb3AuY3N2JykKCiMgQ2FsY3VsYXRlIHRoZSBhdmVyYWdlcyBmb3IgZWFjaCBjdXRvZmYgdmFsdWUgYWNyb3NzIG1vZGVsIHJ1bnMKCmFjY21lYXMubW4gPC0gYWNjbWVhcyAlPiUKICBtdXRhdGUoY3V0b2ZmID0gYXMuY2hhcmFjdGVyKGN1dG9mZikpICU+JQogIGdyb3VwX2J5KGN1dG9mZikgJT4lCiAgc3VtbWFyaXNlKAogICAgcHJNbiA9IG1lYW4ocHJTaXplLG5hLnJtPVQpLCAjIHNpemUgb2YgcHJlc2VuY2UgZGF0YSAobWVhbikKICAgIHByU2QgPSBzZChwclNpemUsbmEucm09VCksICMgc2l6ZSBvZiBwcmVzZW5jZSBkYXRhIChzZCkKICAgIGJnTW4gPSBtZWFuKGJnU2l6ZSxuYS5ybT1UKSwgIyBzaXplIG9mIGJhY2tncm91bmQgZGF0YSAobWVhbikKICAgIGJnU2QgPSBzZChiZ1NpemUsbmEucm09VCksICMgc2l6ZSBvZiBiYWNrZ3JvdW5kIGRhdGEgKHNkKQogICAgZnByTW4gPSBtZWFuKGZwcixuYS5ybT1UKSwgIyBGYWxzZSBQb3NpdGl2ZSBSYXRlIChtZWFuKQogICAgZnByU2QgPSBzZChmcHIsbmEucm09VCksCiAgICB0cHJNbiA9IG1lYW4odHByLG5hLnJtPVQpLCAjIFRydWUgUG9zaXRpdmUgUmF0ZSAobWVhbikKICAgIHRwclNkID0gc2QodHByLG5hLnJtPVQpLAogICAgcHJlY2lzaW9uID0gbWVhbihwcmVjaXNpb24sbmEucm09VCksICMgcHJlY2lzaW9uIChtZWFuKQogICAgcHJlY2lzaW9uU2QgPSBzZChwcmVjaXNpb24sbmEucm09VCksIAogICAgcmVjYWxsID0gbWVhbihyZWNhbGwsbmEucm09VCksICMgcmVjYWxsIChtZWFuKQogICAgcmVjYWxsU2QgPSBzZChyZWNhbGwsbmEucm09VCksCiAgICBmMSA9IG1lYW4oZjEsbmEucm09VCksICMgRjEgc2NvcmUgKG1lYW4pCiAgICBmMVNkID0gc2QoZjEsbmEucm09VCksCiAgICBnbWVhbiA9IG1lYW4oZ21lYW4sbmEucm09VCksICMgR2VvbWV0cmljIE1lYW4gKG1lYW4pCiAgICBnbWVhblNkID0gc2QoZ21lYW4sbmEucm09VCksCiAgICBtY2MgPSBtZWFuKG1jYyxuYS5ybT1UKSwgIyBNYXR0aGV3J3MgQ29ycmVsYXRpb24gQ29lZmZpY2llbnQgKG1lYW4pCiAgICBtY2NTZCA9IHNkKG1jYyxuYS5ybT1UKSwKICAgIGFjY3VyYWN5ID0gbWVhbihhY2N1cmFjeSxuYS5ybT1UKSwgIyBPdmVyYWxsIGFjY3VyYWN5IChtZWFuKQogICAgYWNjdXJhY3lTZCA9IHNkKGFjY3VyYWN5LG5hLnJtPVQpCiAgKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKGN1dG9mZiA9IHJvdW5kKGFzLmRvdWJsZShjdXRvZmYpLDMpKQoKIyBDYWxjdWxhdGUgb3B0aW11bSB0aHJlc2hvbGQgYmFzZWQgb24gRjEgc3RhdGlzdGljCgpjdXRvZmZPcHRNbiA9IGFjY21lYXMubW5bd2hpY2gubWF4KGFjY21lYXMubW4kZjEpLF0kY3V0b2ZmCnByZWNpc2lvbk9wdEYxTW4gPSBhY2NtZWFzLm1uW3doaWNoLm1heChhY2NtZWFzLm1uJGYxKSxdJHByZWNpc2lvbgpyZWNhbGxPcHRGMU1uID0gYWNjbWVhcy5tblt3aGljaC5tYXgoYWNjbWVhcy5tbiRmMSksXSRyZWNhbGwKZnByT3B0TW4gPSBhY2NtZWFzLm1uW3doaWNoLm1heChhY2NtZWFzLm1uJGYxKSxdJGZwck1uCnRwck9wdE1uID0gYWNjbWVhcy5tblt3aGljaC5tYXgoYWNjbWVhcy5tbiRmMSksXSR0cHJNbgptYXhfZjEgPC0gbWF4KGFjY21lYXMubW4kZjEsIG5hLnJtID0gVFJVRSkKCmBgYAoKCmBgYHtyIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQoKIyBST0MgQ3VydmUgYW5kIGxhYmVsIHRoZSBBVUMgdmFsdWUgKGFwcHJveGltYXRpb24pCgojIEdldCB0aGUgQVVDIGFwcHJveAoKIyBFbnN1cmUgZGF0YSBpcyBzb3J0ZWQgYnkgRlBSCmFjY21lYXNfbW5fc29ydGVkIDwtIGFjY21lYXMubW5bb3JkZXIoYWNjbWVhcy5tbiRmcHJNbiksIF0KIyBDb21wdXRlIEFVQyB1c2luZyB0cmFweiBmdW5jdGlvbiBpbiAncHJhY21hJwphdWNfYXZnX2FwcHJveCA8LSB0cmFweihhY2NtZWFzX21uX3NvcnRlZCRmcHJNbiwgYWNjbWVhc19tbl9zb3J0ZWQkdHByTW4pCgpmczJhIDwtIGdncGxvdChkYXRhPWFjY21lYXMpICsKICBnZW9tX2xpbmUoYWVzKHg9ZnByLHk9dHByLGNvbG9yPWZhY3Rvcihtb2RlbCkpLGxpbmV3aWR0aD0wLjQpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzX2Qob3B0aW9uPSJ0dXJibyIpICsKICBnZW9tX2xpbmUoZGF0YT1hY2NtZWFzLm1uLCBhZXMoeCA9IGZwck1uLCB5ID0gdHByTW4pLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAwLjgpICsgICMgUk9DIGN1cnZlIGF2ZXJhZ2UKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxKSkgKyAgIyBTZXQgeCBheGlzIGxpbWl0cyBmcm9tIDAgdG8gMQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHM9YygwLDEpKSArCiAgbGFicyh4PSdGYWxzZSBQb3NpdGl2ZSBSYXRlJywgeT0nVHJ1ZSBQb3NpdGl2ZSBSYXRlJywgdGFnPSJBIikgKwogIGdlb21fcG9pbnQoYWVzKHggPSBmcHJPcHRNbiwgeSA9IHRwck9wdE1uKSwKICAgICAgICAgICAgIGNvbG9yID0gInJlZCIsIHNpemUgPSAzLCBzaGFwZSA9IDE5KSArICAjIG9wdGltYWwgdGhyZXNob2xkIHBvaW50CiAgZ2VvbV90ZXh0KGFlcyh4PWZwck9wdE1uLCB5PXRwck9wdE1uKSwKICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoJ09wdGltYWwgdGhyZXNob2xkOiAnLCByb3VuZChjdXRvZmZPcHRNbiwzKSwnXG5BcHByb3guIEFVQzogJywgcm91bmQoYXVjX2F2Z19hcHByb3gsMykpLAogICAgICAgICAgICBudWRnZV94ID0gMC4zOCwgbnVkZ2VfeSA9IC0wLjA4LCBzaXplID0gMy41KSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSArICAjIHRvIGtlZXAgdGhlIHggYW5kIHkgYXhlcyBzY2FsZXMgc2FtZQogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSArICAjIGRpYWdvbmFsCiAgdGhlbWVfbGlnaHQoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplPTExLGZhY2U9Iml0YWxpYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygwLDAuNCwwLDApLCAiY20iKSksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemU9MTEsZmFjZT0iaXRhbGljIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAuNCwwLDAsMCksICJjbSIpKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMCksCiAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpCgpmczJiIDwtIGdncGxvdChkYXRhPWFjY21lYXMpICsKICBnZW9tX2xpbmUoYWVzKHg9Y3V0b2ZmLHk9ZjEsY29sb3I9ZmFjdG9yKG1vZGVsKSksbGluZXdpZHRoPTAuNCkgKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZChvcHRpb249InR1cmJvIikgKwogIGdlb21fbGluZShkYXRhPWFjY21lYXMubW4sIGFlcyh4PWN1dG9mZiwgeSA9IGYxKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC44KSArICAjIFJPQyBjdXJ2ZSBhdmVyYWdlCiAgIyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9MC40MjQsIGxpbmV0eXBlPSJkYXNoZWQiLCBjb2xvcj0iYmxhY2siKSArCiAgZ2VvbV9wb2ludChhZXMoeD1jdXRvZmZPcHRNbiwgeT1tYXhfZjEpLAogICAgICAgICAgICAgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDMsIHNoYXBlID0gMTkpICsKICBnZW9tX3RleHQoYWVzKHg9Y3V0b2ZmT3B0TW4sIHk9bWF4X2YxKSwKICAgICAgICAgICAgbGFiZWwgPSBwYXN0ZTAoJ09wdGltYWwgdGhyZXNob2xkOiAnLCByb3VuZChjdXRvZmZPcHRNbiwzKSksCiAgICAgICAgICAgIG51ZGdlX3ggPSAwLjAsIG51ZGdlX3kgPSAwLjA4LCBzaXplID0gMy41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKDAsMSkpICsgICMgU2V0IHggYXhpcyBsaW1pdHMgZnJvbSAwIHRvIDEKICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwxKSkgKwogIGxhYnMoeD0nVGhyZXNob2xkJywgeT0nRjEgU2NvcmUnLCB0YWc9IkIiKSArCiAgY29vcmRfZml4ZWQocmF0aW8gPSAxKSArICAjIHRvIGtlZXAgdGhlIHggYW5kIHkgYXhlcyBzY2FsZXMgc2FtZQogIHRoZW1lX2xpZ2h0KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZT0xMSxmYWNlPSJpdGFsaWMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMCwwLjQsMCwwKSwgImNtIikpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplPTExLGZhY2U9Iml0YWxpYyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygwLjQsMCwwLDApLCAiY20iKSksCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTApLAogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKQoKKGZzMiA8LSBnZ2FycmFuZ2UoZnMyYSxmczJiKSkKCmdnc2F2ZShmczIsIGZpbGU9Ii4uLy4uL2ZpZ3VyZXMvRmlndXJlUzJfQVVDX0YxTWF4LnBuZyIsIGRwaT0zMDApCgpybShmczIsZnMyYSxmczJiLGFjY21lYXNfbW5fc29ydGVkLGF1Y19hdmdfYXBwcm94KQoKYGBgCgpUYWJsZSBTMTogUGVyZm9ybWFuY2UgbWV0cmljcyBmb3IgdGhlIG9wdGltdW0gY3V0b2ZmIHZhbHVlCgpDcmVhdGUgYSBwcmV0dHkgdGFibGUuCgpgYGB7cn0KCmxpYnJhcnkoZmxleHRhYmxlLCBxdWlldGx5ID0gVCkKCiMgR2V0IHRoZSBiZXN0IEYxIHNjb3JlIGZvciBlYWNoIG1vZGVsIHJ1bgphY2NtZWFzLmJlc3QgPC0gYWNjbWVhcyAlPiUgCiAgbXV0YXRlKG1vZGVsID0gYXMuZmFjdG9yKG1vZGVsKSkgJT4lCiAgZ3JvdXBfYnkobW9kZWwpICU+JSAKICB0b3BfbigxLGYxKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKG1vZGVsX2l0ZXIgPSByb3dfbnVtYmVyKCkpICU+JQogIHNlbGVjdChtb2RlbCxwclNpemUsYmdTaXplLHRwcixwcmVjaXNpb24scmVjYWxsLGYxLGN1dG9mZikKCmhlYWQoYWNjbWVhcy5iZXN0LDEwKQoKIyBGaXggbmFtZXMgYW5kIGFkZCB1bml0cwpuYW1lcyhhY2NtZWFzLmJlc3QpIDwtIGMoIk1vZGVsIFNlZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIiMgb2YgUHJlc2VuY2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgIiMgb2YgQmFja2dyb3VuZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiVHJ1ZSBQb3NpdGl2ZSBSYXRlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICJQcmVjaXNpb24iLAogICAgICAgICAgICAgICAgICAgICAgICAgIlJlY2FsbCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAiRjEtU2NvcmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgIlRocmVzaG9sZCIpCgojIFNldCBmb250IG5hbWUgZm9yIHRhYmxlCmZvbnRuYW1lIDwtICJUaW1lcyBOZXcgUm9tYW4iCgojIENyZWF0ZSB0aGUgZmxleHRhYmxlCihmdDEgPC0gZmxleHRhYmxlKGFjY21lYXMuYmVzdCkgJT4lCiBmb250KGZvbnRuYW1lID0gZm9udG5hbWUsIHBhcnQgPSAiYWxsIikgJT4lCiBhdXRvZml0KCkgJT4lIGZpdF90b193aWR0aCg2LjUpKQpwcmludChmdDEsIHByZXZpZXcgPSAiZG9jeCIpCgojIFdyaXRlIHRvIGEgQ1NWCndyaXRlX2NzdihhY2NtZWFzLmJlc3QsICIuLi8uLi9maWd1cmVzL1RhYmxlUzFfQWNjdXJhY3lfTWF4RjEuY3N2IikKCmBgYAoKQ2xlYW4gdXAhCgpgYGB7cn0KCmBgYAo=